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

📄 au1xxx_pm.patch

📁 patches for linux-2.6.
💻 PATCH
📖 第 1 页 / 共 5 页
字号:
+	char data_in[MAX_POWER_CONF_LEN];+	au1xxx_power_dev_t *dev = (au1xxx_power_dev_t *)data;++	DPRINTK("Entering proc_write_timer\n");+	+	if (count > MAX_POWER_CONF_LEN)+		len = MAX_POWER_CONF_LEN;+	else+		len = count;++	DPRINTK("Doing copy_from_user with len: %d\n", len);+	if (copy_from_user(data_in, buffer, len))+		return -EFAULT;++	/* read in the value */+	if (au1xxx_pm_setup->feedback_mode == ASCII_FEEDBACK) {+		if (sscanf(data_in, "%lu\n", &timeout_val) != 1) {+			printk(KERN_ERR "Kernel Error: Cannot read new power management settings.\n"); 			return -EFAULT; 		}+	} else if (au1xxx_pm_setup->feedback_mode == BINARY_FEEDBACK) {+		DPRINTK("Attempting to write settings via BINARY_FEEDBACK method.\n");+		/* For some reason it doesn't work when you try and do this piece by piece+		 * so I've simply created a structure to do it all at once. */+		memcpy(&timeout_val, &data_in, sizeof(unsigned long));+		size = sizeof(unsigned long);+	} else {+		/* reset feedback mode in the error case */+		printk(KERN_WARNING "Invalid power management feedback setting; resetting to default.\n");+		spin_lock_irqsave(&au1xxx_pm_lock, spin_lock_flags);+		au1xxx_pm_setup->feedback_mode = DEFAULT_FEEDBACK;+		spin_unlock_irqrestore(&au1xxx_pm_lock, spin_lock_flags);+		return -EFAULT;+	}++	/* convert the input from seconds into CPU ticks */+	timeout_val = (unsigned long) (timeout_val * HZ);+	+	/* actually make the changes */+	spin_lock_irqsave(&au1xxx_pm_lock, spin_lock_flags);+	if ((timeout_val) && (dev->timeout)) {+		dev->timeout = timeout_val;+		mod_timer(&dev->timer, jiffies + dev->timeout);+	} else if ((!timeout_val) && (dev->timeout)) {+		dev->timeout = timeout_val;+		del_timer(&dev->timer);+	} else if ((timeout_val) && (!dev->timeout)) {+		dev->timeout = timeout_val;+		init_timer(&dev->timer);+		dev->timer.function = &au1xxx_pm_service_timer;+		dev->timer.expires = jiffies + dev->timeout;+		dev->timer.data = (unsigned long)dev;+		add_timer(&dev->timer);+	} else if ((!timeout_val) && (!dev->timeout)) {+		/* do nothing in this case, as the timeout is still nothing */+	}+	spin_unlock_irqrestore(&au1xxx_pm_lock, spin_lock_flags);++	return len;+}++static int proc_read_pending(char *page, char **start, off_t off, +	int count, int *eof, void *data)+{+	int current_pending = 0;+	int size = 0;+	int i;+	au1xxx_pm_bin_header_t my_bin_hdr;++	/* add up all the pending flags for registered devices */+	for (i = 0; i < MAX_SUPPORTED_DEVICES; i++) {+		if (sys_power_pointers[i]->valid)+			current_pending += sys_power_pointers[i]->state_change_pending;+	}++	if (au1xxx_pm_setup->feedback_mode == ASCII_FEEDBACK) {+		size += sprintf((page + size), "Current pending transactions: %d\n", +			current_pending);++		/* handle the buffer */+  	if (size <= off + count) +			*eof = 1;+  	*start = page + off;+  	size -= off;+  	if (size > count) +			size = count;+  	if (size < 0) +			size = 0;+	} else if (au1xxx_pm_setup->feedback_mode == BINARY_FEEDBACK) {+		my_bin_hdr.report_type = AU1XXX_PM_PENDING;+		my_bin_hdr.num_reports = 1;+		memcpy((page + size), &my_bin_hdr, sizeof(au1xxx_pm_bin_header_t));+		size += sizeof(au1xxx_pm_bin_header_t);+		memcpy((page + size), &current_pending, sizeof(int));+		size += sizeof(int);+	} else {+		/* reset feedback mode in the error case */+		printk(KERN_WARNING "Invalid power management feedback setting; resetting to default.\n");+		spin_lock_irqsave(&au1xxx_pm_lock, spin_lock_flags);+		au1xxx_pm_setup->feedback_mode = DEFAULT_FEEDBACK;+		spin_unlock_irqrestore(&au1xxx_pm_lock, spin_lock_flags);+		return -EFAULT;+	} -		old_baud_base = get_au1x00_uart_baud_base();-		old_cpu_freq = get_au1x00_speed();+	return size;+}++static int proc_read_error(char *page, char **start, off_t off, +	int count, int *eof, void *data)+{+	int size = 0;+	int i;+	au1xxx_pm_error_t *error = (au1xxx_pm_error_t *)data;+	au1xxx_pm_bin_header_t my_bin_hdr; -		new_cpu_freq = pll * 12 * 1000000;-	        new_baud_base =  (new_cpu_freq / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16));-		set_au1x00_speed(new_cpu_freq);-		set_au1x00_uart_baud_base(new_baud_base);--		old_refresh = au_readl(MEM_SDREFCFG) & 0x1ffffff;-		new_refresh =-		    ((old_refresh * new_cpu_freq) /-		     old_cpu_freq) | (au_readl(MEM_SDREFCFG) & ~0x1ffffff);--		au_writel(pll, SYS_CPUPLL);-		au_sync_delay(1);-		au_writel(new_refresh, MEM_SDREFCFG);-		au_sync_delay(1);--		for (i = 0; i < 4; i++) {-			if (au_readl-			    (UART_BASE + UART_MOD_CNTRL +-			     i * 0x00100000) == 3) {-				old_clk =-				    au_readl(UART_BASE + UART_CLK +-					  i * 0x00100000);-				// baud_rate = baud_base/clk-				baud_rate = old_baud_base / old_clk;-				/* we won't get an exact baud rate and the error-				 * could be significant enough that our new-				 * calculation will result in a clock that will-				 * give us a baud rate that's too far off from-				 * what we really want.-				 */-				if (baud_rate > 100000)-					baud_rate = 115200;-				else if (baud_rate > 50000)-					baud_rate = 57600;-				else if (baud_rate > 30000)-					baud_rate = 38400;-				else if (baud_rate > 17000)-					baud_rate = 19200;-				else-					(baud_rate = 9600);-				// new_clk = new_baud_base/baud_rate-				new_clk = new_baud_base / baud_rate;-				au_writel(new_clk,-				       UART_BASE + UART_CLK +-				       i * 0x00100000);-				au_sync_delay(10);+	if (au1xxx_pm_setup->feedback_mode == ASCII_FEEDBACK) {+		/* print all error information */++		if (!error->dev) {+			size += sprintf((page + size), "There are no errors registered with the power management system.\n");+		}+		else {+			for (i = 0; i < MAX_SUPPORTED_ERRORS; i++) {+				if (sys_error_pointers[i]->dev) {+					size += sprintf((page + size), "-----------------------------\n");+					size += sprintf((page + size), "Device Name: %s\nError Code: %d\nOccurances: %d\nFirst Occurance: %d\nLatest Occurance: %d\n",+						sys_error_pointers[i]->dev->name,+						sys_error_pointers[i]->error_code,+						sys_error_pointers[i]->error_count,+						(int) sys_error_pointers[i]->first_timestamp.tv_sec,+						(int) sys_error_pointers[i]->last_timestamp.tv_sec);+				} 			} 		}+		/* handle the buffer */+  	if (size <= off + count) +			*eof = 1;+  	*start = page + off;+  	size -= off;+  	if (size > count) +			size = count;+  	if (size < 0) +			size = 0;+	} else if (au1xxx_pm_setup->feedback_mode == BINARY_FEEDBACK) {+		/* output all error info in binary format */+		for (i = 0; i < MAX_SUPPORTED_ERRORS; i++) {+			memcpy((page + size), &my_bin_hdr, sizeof(au1xxx_pm_bin_header_t));+			size += sizeof(au1xxx_pm_bin_header_t);+			memcpy((page + size), sys_error_pointers[i], sizeof(au1xxx_pm_error_t));+			size += sizeof(au1xxx_pm_error_t);+		}+	} else {+		/* reset feedback mode in the error case */+		printk(KERN_WARNING "Invalid power management feedback setting; resetting to default.\n");+		spin_lock_irqsave(&au1xxx_pm_lock, spin_lock_flags);+		au1xxx_pm_setup->feedback_mode = DEFAULT_FEEDBACK;+		spin_unlock_irqrestore(&au1xxx_pm_lock, spin_lock_flags);+		return -EFAULT;+	}+	+	/* clear all error information */+	spin_lock_irqsave(&au1xxx_pm_lock, spin_lock_flags);+	for (i = 0; i < MAX_SUPPORTED_ERRORS; i++) {+		remove_au1xxx_pm_error(sys_error_pointers[i]); 	}+	spin_unlock_irqrestore(&au1xxx_pm_lock, spin_lock_flags); +	return size;+}+++/***********************************************************************+ *                     PM DEVICE FUNCTIONS+ ***********************************************************************/+au1xxx_power_dev_t *new_au1xxx_power_device(const char *name, +		au1xxx_power_callback cb_func, void *data)+{+	int i;+	au1xxx_power_dev_t *new_dev = NULL;++	DPRINTK("Entering new_au1xxx_power_device()\n");++	spin_lock_irqsave(&au1xxx_pm_lock, spin_lock_flags);++	/* find the first free dev node */+	for (i = 0; i < MAX_SUPPORTED_DEVICES; i++) {+		if (sys_power_pointers[i]->valid == 0) {+			new_dev = sys_power_pointers[i];+			break;+		}+	}++	if (new_dev == NULL) {+		printk(KERN_ERR "Kernel Error: No memory for a new power device.\n");+		return NULL;+	}++	/* initialze the new device node */+	strncpy(new_dev->name, name, MAX_NAME_WIDTH);+	new_dev->callback = *cb_func;+	new_dev->valid = 1;+	new_dev->prev_state = SLEEP_STATE;+	do_gettimeofday(&(new_dev->prev_state_timestamp));+	new_dev->cur_state = AWAKE_STATE;+	do_gettimeofday(&(new_dev->cur_state_timestamp));+	new_dev->data = data;+	new_dev->timeout = 0;+	+	/* Create a /proc/pm entry for both read and write if the system has loaded+	 * the proc_fs driver. */+	if (system_dev->proc_entry != NULL) {+		DPRINTK("Creating a /proc/pm entry for the new device.\n");+		new_dev->proc_entry = create_proc_entry(name, 0644, power_dir);+		if (new_dev->proc_entry == NULL) +			goto no_new_proc_entry;+		new_dev->proc_entry->data = new_dev;+		new_dev->proc_entry->read_proc = proc_read;+		new_dev->proc_entry->write_proc = proc_write;+	} else {+		/* This is not an error condition.  It is the case that occurs when a+		 * driver loads a power management device before the power management+		 * driver itself is loaded. */+		new_dev->proc_entry = NULL;+	}++	/* Create a /proc/pm/timeout entry for both read and write if the system has+	 * loaded the proc_fs driver. */++	if (system_dev->timer_proc_entry != NULL) {+		DPRINTK("Creating a /proc/pm/timeout entry for the new device.\n");+		new_dev->timer_proc_entry = create_proc_entry(name, 0644, timeout_dir);+		if (new_dev->timer_proc_entry == NULL) +			goto no_new_timer_proc_entry;+		new_dev->timer_proc_entry->data = new_dev;+		new_dev->timer_proc_entry->read_proc = proc_read_timer;+		new_dev->timer_proc_entry->write_proc = proc_write_timer;+	} else {+		/* This is not an error condition.  It is the case that occurs when a+		 * driver loads a power management device before the power management+		 * driver itself is loaded. */+		new_dev->timer_proc_entry = NULL;+	}++	spin_unlock_irqrestore(&au1xxx_pm_lock, spin_lock_flags);+	+	DPRINTK("Returning from new_au1xxx_power_device() with a new device.\n");+	return new_dev;++	remove_proc_entry(new_dev->name, timeout_dir);+no_new_timer_proc_entry:+	remove_proc_entry(new_dev->name, power_dir);+no_new_proc_entry:++	printk(KERN_WARNING "Unable to create a /proc entry for a new power management device.\n");+	return NULL;+}++int remove_au1xxx_power_device(au1xxx_power_dev_t *dev) {+	int retval = 0;++	spin_lock_irqsave(&au1xxx_pm_lock, spin_lock_flags);++	if ((system_dev->proc_entry == NULL) || (dev == NULL)) {+		retval = ERROR_INVALID_DEVICE;+		printk(KERN_WARNING "Power management error: accessing invalid device.\n");+		return retval;+	}++	/* clear the device from the array */+	dev->valid = 0;+	strncpy(dev->name, "", strlen(""));+	dev->callback = NULL;+	dev->cur_state = SLEEP_STATE;+	do_gettimeofday(&(dev->cur_state_timestamp));+	dev->prev_state = SLEEP_STATE;+	do_gettimeofday(&(dev->prev_state_timestamp));+	dev->data = NULL;+	dev->timeout = 0;++	/* remove the proc entries if they exist */+	if (dev->proc_entry) +		remove_proc_entry(dev->name, power_dir);+	if (dev->timer_proc_entry) +		remove_proc_entry(dev->name, timeout_dir);++	spin_unlock_irqrestore(&au1xxx_pm_lock, spin_lock_flags); -	/* We don't want _any_ interrupts other than-	 * match20. Otherwise our calibrate_delay()-	 * calculation will be off, potentially a lot.-	 */-	intc0_mask = save_local_and_disable(0);-	intc1_mask = save_local_and_disable(1);-	local_enable_irq(AU1000_TOY_MATCH2_INT);-	spin_unlock_irqrestore(&pm_lock, flags);-	calibrate_delay();-	restore_local_and_enable(0, intc0_mask);-	restore_local_and_enable(1, intc1_mask); 	return retval; } +au1xxx_pm_error_t *new_au1xxx_pm_error(int error_code, au1xxx_power_dev_t *dev) {+	au1xxx_pm_error_t *ret_error_t = NULL;+	int i;++	if (dev == NULL) {+		ret_error_t = NULL;+		printk(KERN_ERR "Invalid Au1xxx power management device access.\n");+		return ret_error_t;+	} -static struct ctl_table pm_table[] = {-	{ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, &pm_do_suspend},-	{ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &pm_do_sleep},-	{CTL_ACPI, "freq", NULL, 0, 0600, NULL, &pm_do_freq},-	{0}-};+	/* find a matching error structure or a free error struct */+	for (i = 0; i < MAX_SUPPORTED_ERRORS; i++) {+		if (sys_error_pointers[i]->dev == dev)+			break;+		/* each device is allowed one error structure, so if it has an allocated+		 * structre, return it */+		else if (sys_error_pointers[i]->dev == NULL)+			break;+	}+	if (i == MAX_SUPPORTED_ERRORS) {+		ret_error_t = NULL;+		printk(KERN_ERR "No available resources for power management error reporting.\n");+		return ret_error_t;+	} -static struct ctl_table pm_dir_table[] = {-	{CTL_ACPI, "pm", NULL, 0, 0555, pm_table},-	{0}-};+	/* update the error structure */+	if ((sys_error_pointers[i]->dev == dev) &&+		(sys_error_pointers[i]->error_code == error_code)) {+		sys_error_pointers[i]->error_count++;+		do_gettimeofday(&(sys_error_pointers[i]->last_timestamp));+	}+	/* the 'else' case handles new error structure as well as devices+	 * experiencing a new error */

⌨️ 快捷键说明

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