📄 au1xxx_pm.patch
字号:
+ ret = call_usermodehelper(modprobe_path_pm, argv, envp, 1);+ break;++ case AU1XXX_PM_WAKEUP:+ argv[2] = add;+ ret = call_usermodehelper(modprobe_path_pm, argv, envp, 1);+ break;++ case AU1XXX_PM_ACCESS:+ if (dev->cur_state != AWAKE_STATE) {+ /* do nothing */+ }+ else+ ret = -1;+ break;++ case AU1XXX_PM_GETSTATUS:+ ret = dev->cur_state;+ break;++ default:+ case AU1XXX_PM_IDLE:+ case AU1XXX_PM_CLEANUP:+ break;+ }++ return ret;+}+++/***********************************************************************+ * PROC INTERFACE FUNCTIONS+ ***********************************************************************/+static int proc_read(char *page, char **start, off_t off, + int count, int *eof, void *data)+{+ int size = 0;+ int i;+ au1xxx_power_dev_t *power_dev = (au1xxx_power_dev_t *)data;+ struct au1xxx_pm_bin_header bin_hdr;+ au1xxx_pm_bin_header_t *bin_header = &bin_hdr;++ if (!power_dev->valid) {+ printk(KERN_ERR "Kernel Error: Attempted to read from an invalid power device.\n");+ return -EFAULT;+ }++ if (au1xxx_pm_setup->feedback_mode == ASCII_FEEDBACK) {+ /* print out the info on the current device */+ size = sprintf((page + size), "Device Name: %s\nPower State: %d\nDevice Status: %d\nPending Transitions: %d\nError Code: %d\n", + power_dev->name, + power_dev->cur_state, + power_dev->callback(power_dev, AU1XXX_PM_GETSTATUS, NULL),+ power_dev->state_change_pending,+ power_dev->last_error);+ + /* print all the devices' info if reading the system entry */+ if (power_dev == system_dev) {+ for (i = 1; i < MAX_SUPPORTED_DEVICES; i++) {+ if (sys_power_pointers[i]->valid) {+ size += sprintf((page + size), "-----------------------------\n");+ size += sprintf((page + size), "Device Name: %s\nPower State: %d\nDevice Status: %d\nPending Transitions: %d\nError Code: %d\n", + sys_power_pointers[i]->name, + sys_power_pointers[i]->cur_state, + sys_power_pointers[i]->callback(sys_power_pointers[i], + AU1XXX_PM_GETSTATUS, NULL),+ sys_power_pointers[i]->state_change_pending,+ sys_power_pointers[i]->last_error);+ }+ } }- if (copy_from_user(buf, buffer, *len)) {- spin_unlock_irqrestore(&pm_lock, flags);- return -EFAULT;++ /* 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) {+ DPRINTK("Starting BINARY_FEEDBACK output method\n");++ if (power_dev != system_dev) {+ /* copy a header for a single binary report */+ bin_header->report_type = AU1XXX_PM_DEVICE;+ bin_header->num_reports = 1;+ size = sizeof(au1xxx_pm_bin_header_t);+ memcpy(page, bin_header, size);++ /* copy the actual report */+ memcpy((page + size), power_dev, sizeof(au1xxx_pm_public_dev_t));+ size += sizeof(au1xxx_pm_public_dev_t);++ DPRINTK("report_type Size: %d\t\tValue: %d\n", sizeof(bin_header->report_type), (int) bin_header->report_type);+ DPRINTK("num_reports Size: %d\t\tValue: %d\n", sizeof(bin_header->num_reports), (int) bin_header->num_reports);+ DPRINTK("Total size returned: %d\n", size);+ } else {+ /* copy a header for a full system report */+ bin_header->report_type = AU1XXX_PM_DEVICE;+ bin_header->num_reports = MAX_SUPPORTED_DEVICES;+ size = sizeof(au1xxx_pm_bin_header_t);+ memcpy(page, bin_header, size);++ /* copy the full system report */+ for (i = 0; i < MAX_SUPPORTED_DEVICES; i++) {+ memcpy((page + size), sys_power_pointers[i], sizeof(au1xxx_pm_public_dev_t));+ size += sizeof(au1xxx_pm_public_dev_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;+ }++ return size;+}++static int proc_write(struct file *file, const char *buffer, + unsigned long count, void *data)+{+ int len;+ int callback_ret_val;+ char data_in[MAX_POWER_CONF_LEN];+ au1xxx_power_dev_t *power_dev = (au1xxx_power_dev_t *)data;+ int power_level;++ DPRINTK("Entering proc_write\n");++ if (!power_dev->valid) {+ printk(KERN_ERR "Kernel Error: Attempted write to an invalid power device.\n");+ return -EFAULT;+ }++ if (count > MAX_POWER_CONF_LEN)+ len = MAX_POWER_CONF_LEN;+ else+ len = count;++ if (copy_from_user(data_in, buffer, len))+ return -EFAULT;++ if (au1xxx_pm_setup->feedback_mode == ASCII_FEEDBACK) {+ power_level = simple_strtoul(data_in, NULL, 0);+ DPRINTK("Used ASCII_FEEDBACK to get power_level of %d\n", power_level);+ } else if (au1xxx_pm_setup->feedback_mode == BINARY_FEEDBACK) {+ memcpy(&power_level, data_in, sizeof(int));+ DPRINTK("Used BINARY_FEEDBACK to get power_level of %d\n", power_level);+ } 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;+ }++ spin_lock_irqsave(&au1xxx_pm_lock, spin_lock_flags);+ if (power_level != SLEEP_STATE) {+ power_dev->prev_state = power_dev->cur_state;+ power_dev->prev_state_timestamp = power_dev->cur_state_timestamp;+ do_gettimeofday(&(power_dev->cur_state_timestamp));+ power_dev->cur_state = power_level; + power_dev->state_change_pending = TRUE;+ DPRINTK("Waking up %s device.\n", power_dev->name);+ callback_ret_val = power_dev->callback(power_dev, AU1XXX_PM_WAKEUP, &power_level);+ power_dev->state_change_pending = FALSE;+ power_dev->last_error = callback_ret_val;+ } else {+ power_dev->prev_state = power_dev->cur_state;+ power_dev->prev_state_timestamp = power_dev->cur_state_timestamp;+ do_gettimeofday(&(power_dev->cur_state_timestamp));+ power_dev->cur_state = power_level;+ power_dev->state_change_pending = TRUE;+ DPRINTK("Putting %s device to sleep.\n", power_dev->name);+ callback_ret_val = power_dev->callback(power_dev, AU1XXX_PM_SLEEP, &power_level);+ power_dev->state_change_pending = FALSE;+ power_dev->last_error = callback_ret_val;+ }+ spin_unlock_irqrestore(&au1xxx_pm_lock, spin_lock_flags);++ return len;+}++static int proc_read_settings(char *page, char **start, off_t off, + int count, int *eof, void *data)+{+ int size = 0;++ if ((!au1xxx_pm_setup->valid) || + (au1xxx_pm_setup != (au1xxx_pm_settings_t *)data))+ {+ printk(KERN_ERR "Kernel Error: Power Management settings are invalid.\n");+ return -EFAULT;+ }++ if (au1xxx_pm_setup->feedback_mode == ASCII_FEEDBACK) {+ size = sprintf((page + size), "Au1xxx Power Management Settings:\n");+ size += sprintf((page + size), "=================================\n");++ size += sprintf((page + size), "Current wakeup method is: ");+ if (au1xxx_pm_setup->wakeup_mode == GPIO_WAKEUP) + size += sprintf((page + size), "GPIO 5 controlled.\n");+ else if (au1xxx_pm_setup->wakeup_mode == TIMER_WAKEUP) {+ size += sprintf((page + size), "TOY timer controlled.\n");+ size += sprintf((page + size), " Current sleep time: %d seconds.\n", + au1xxx_pm_setup->sleep_time); }- buf[*len] = 0;- p = buf;- val = simple_strtoul(p, &p, 0);- if (val > MAX_CPU_FREQ) {- spin_unlock_irqrestore(&pm_lock, flags);+ else+ size += sprintf((page + size), "invalid.\n");+ + size += sprintf((page + size), "Current feedback method is: ");+ if (au1xxx_pm_setup->feedback_mode == ASCII_FEEDBACK)+ size += sprintf((page + size), "ASCII text file.\n");+ else if (au1xxx_pm_setup->feedback_mode == BINARY_FEEDBACK)+ size += sprintf((page + size), "Binary file.\n");+ else+ size += sprintf((page + size), "invalid.\n");++ /* 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) {+ DPRINTK("Attempting to read settings via BINARY_FEEDBACK method.\n");+ memcpy((page + size), &au1xxx_pm_setup->wakeup_mode, sizeof(int));+ size += sizeof(int);+ memcpy((page + size), &au1xxx_pm_setup->sleep_time, size);+ size += sizeof(int);+ memcpy((page + size), &au1xxx_pm_setup->feedback_mode, size);+ 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;+ }++ return size;+}++static int proc_write_settings(struct file *file, const char *buffer, + unsigned long count, void *data)+{+ int len, wakeup_int, feedback_int;+ unsigned int sleep_int;+ int size = 0;+ char data_in[MAX_POWER_CONF_LEN];+ struct { + unsigned int wakeup_uns;+ unsigned int sleep_uns;+ unsigned int feedback_uns;+ } binary_reader;++ DPRINTK("Entering proc_write_settings\n");++ if ((!au1xxx_pm_setup->valid) ||+ (au1xxx_pm_setup != (au1xxx_pm_settings_t *)data))+ {+ printk(KERN_ERR "Kernel Error: Power Management settings are invalid.\n");+ return -EFAULT;+ }++ 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 thre values according to the feedback mode */+ if (au1xxx_pm_setup->feedback_mode == ASCII_FEEDBACK) {+ if (sscanf(data_in, "%d:%d, %u\n", &wakeup_int, &sleep_int, + &feedback_int) != 3) {+ 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(&binary_reader, &data_in, sizeof(binary_reader));+ size = sizeof(binary_reader);+ wakeup_int = (int) binary_reader.wakeup_uns;+ sleep_int = (int) binary_reader.sleep_uns;+ feedback_int = (int) binary_reader.feedback_uns;+ } 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;+ }+ + /* actually record the changes */+ spin_lock_irqsave(&au1xxx_pm_lock, spin_lock_flags);+ if (wakeup_int == GPIO_WAKEUP)+ au1xxx_pm_setup->wakeup_mode = GPIO_WAKEUP;+ else if (wakeup_int == TIMER_WAKEUP) {+ au1xxx_pm_setup->wakeup_mode = TIMER_WAKEUP;+ au1xxx_pm_setup->sleep_time = (int) sleep_int;+ }+ else {+ au1xxx_pm_setup->wakeup_mode = DEFAULT_WAKEUP;+ printk(KERN_WARNING "Invalid power management wakeup mode; resetting to default.\n");+ } - pll = val / 12;- if ((pll > 33) || (pll < 7)) { /* 396 MHz max, 84 MHz min */- /* revisit this for higher speed cpus */- spin_unlock_irqrestore(&pm_lock, flags);+ if (feedback_int == ASCII_FEEDBACK)+ au1xxx_pm_setup->feedback_mode = ASCII_FEEDBACK;+ else if (feedback_int == BINARY_FEEDBACK)+ au1xxx_pm_setup->feedback_mode = BINARY_FEEDBACK;+ else {+ au1xxx_pm_setup->feedback_mode = DEFAULT_FEEDBACK;+ printk(KERN_WARNING "Invalid power management feedback mode; resetting to default.\n");+ }+ spin_unlock_irqrestore(&au1xxx_pm_lock, spin_lock_flags);++ return len;+}++static int proc_read_timer(char *page, char **start, off_t off, + int count, int *eof, void *data)+{+ int size = 0;+ au1xxx_power_dev_t *dev = (au1xxx_power_dev_t *)data;+ au1xxx_pm_bin_header_t my_bin_hdr;++ if (au1xxx_pm_setup->feedback_mode == ASCII_FEEDBACK) {+ size += sprintf((page + size), "Timeout: %lu\n", dev->timeout);++ /* 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_TIMEOUT;+ 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), &dev->timeout, 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;+ }++ return size;+}++static int proc_write_timer(struct file *file, const char *buffer, + unsigned long count, void *data)+{+ int len;+ unsigned long timeout_val = 0;+ int size = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -