📄 au1xxx_pm.patch
字号:
+ else {+ sys_error_pointers[i]->dev = dev;+ sys_error_pointers[i]->error_code = error_code;+ sys_error_pointers[i]->error_count = 1;+ do_gettimeofday(&(sys_error_pointers[i]->first_timestamp));+ do_gettimeofday(&(sys_error_pointers[i]->last_timestamp));+ }++ return ret_error_t;+}++int remove_au1xxx_pm_error(au1xxx_pm_error_t *error) {+ int retval = 0;++ if (error == NULL) {+ retval = -EFAULT;+ printk("Invalid Au1xxx power management error access.\n");+ return retval;+ }++ error->dev = NULL;+ error->error_code = 0;+ error->error_count = 0;+ error->first_timestamp = zero_timeval;+ error->last_timestamp = zero_timeval;++ return retval;+}++int au1xxx_pm_access(au1xxx_power_dev_t *dev) {+ int retval = 0;++ if ((system_dev->proc_entry == NULL) || + (dev == NULL) || + !system_dev->valid) {+ retval = ERROR_INVALID_DEVICE;+ printk(KERN_WARNING "Power management error: accessing invalid device.\n");+ return retval;+ }++ spin_lock_irqsave(&au1xxx_pm_lock, spin_lock_flags);+ /* turn the device on if it's not already */+ if (!dev->cur_state) {+ dev->prev_state = dev->cur_state;+ dev->prev_state_timestamp = dev->cur_state_timestamp;+ dev->cur_state = AWAKE_STATE;+ do_gettimeofday(&(dev->cur_state_timestamp));+ retval = dev->callback(dev, AU1XXX_PM_ACCESS, NULL);+ }+ spin_unlock_irqrestore(&au1xxx_pm_lock, spin_lock_flags);++ /* reset the timeout, if enabled */+ if (dev->timeout)+ mod_timer(&dev->timer, jiffies + dev->timeout);++ /* always reset the system device's timeout, if enabled */+ if (system_dev->timeout)+ mod_timer(&system_dev->timer, jiffies + system_dev->timeout);++ /* handle errors */+ if (retval) + new_au1xxx_pm_error(retval, dev);++ /* setup locking/timed/discrete event sim system for keeping hardware on */+ /* maybe just disable interrupts? */+ + return retval;+}++int au1xxx_pm_idle(au1xxx_power_dev_t *dev) {+ int retval = 0;++ /* return a warning if the main driver isn't loaded */+ if ((system_dev->proc_entry == NULL) || + (dev == NULL) || + !system_dev->valid) {+ retval = ERROR_INVALID_DEVICE;+ printk(KERN_WARNING "Power management error: accessing invalid device.\n");+ return retval;+ }++ spin_lock_irqsave(&au1xxx_pm_lock, spin_lock_flags);+ /* turn the device off if it's currently on */+ if (dev->cur_state) {+ dev->prev_state = dev->cur_state;+ dev->prev_state_timestamp = dev->cur_state_timestamp;+ dev->cur_state = SLEEP_STATE;+ do_gettimeofday(&(dev->cur_state_timestamp));+ retval = dev->callback(dev, AU1XXX_PM_IDLE, NULL);+ }+ spin_unlock_irqrestore(&au1xxx_pm_lock, spin_lock_flags);++ /* reset the timeout, if enabled */+ if (dev->timeout)+ mod_timer(&dev->timer, jiffies + dev->timeout);++ /* always reset the system device's timeout, if enabled */+ if (system_dev->timeout)+ mod_timer(&system_dev->timer, jiffies + system_dev->timeout); ++ /* handle errors */+ if (retval) + new_au1xxx_pm_error(retval, dev);++ return retval;+}++static void au1xxx_pm_service_timer(unsigned long var) { + int power_level = SLEEP_STATE;+ au1xxx_power_dev_t *dev = (au1xxx_power_dev_t *)var;++ /* handle the timeout */+ if (dev->cur_state != SLEEP_STATE)+ dev->callback(dev, AU1XXX_PM_SLEEP, &power_level); ++ /* reinstall timer */+ if (dev->timeout)+ mod_timer(&dev->timer, jiffies + dev->timeout);++ return;+}++int au1xxx_pm_set_timer(au1xxx_power_dev_t *dev, unsigned long timeout_val) { + int retval = 0;++ if (dev == NULL) {+ retval = -EFAULT;+ } else if ((timeout_val) && (dev->timeout)) {+ /* modify the existing timer */+ dev->timeout = timeout_val;+ mod_timer(&dev->timer, jiffies + dev->timeout);+ } else if ((!timeout_val) && (dev->timeout)) {+ /* delete the existing timer */+ dev->timeout = timeout_val;+ del_timer(&dev->timer);+ } else if ((timeout_val) && (!dev->timeout)) {+ /* install the timer if there was no previous timer */+ 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 */+ }++ return retval;+}++int au1xxx_pm_reset_timer(au1xxx_power_dev_t *dev) { + int retval = 0;++ if (dev == NULL) {+ retval = -EFAULT;+ } else if (dev->timeout) {+ /* reset the existing timer */+ mod_timer(&dev->timer, jiffies + dev->timeout);+ } else if (!dev->timeout) {+ /* do nothing in this case, as the timeout is nothing */+ }++ return retval;+} -/*- * Initialize power interface+int au1xxx_pm_del_timer(au1xxx_power_dev_t *dev) { + int retval = 0;++ if (dev == NULL) {+ retval = -EFAULT;+ } else if (dev->timeout == 0) {+ /* do nothing */+ } else {+ retval = del_timer(&dev->timer);+ }++ return retval;+}+/***********************************************************************+ * INITIALIZE POWER INTERFACE+ ***********************************************************************/+/* PM Catch All Init funtion */++void pm_catchall_pm_init(void)+{+ int i;++ printk("Power Managed Modules Support:\n");+ for(i=0; i<num_modules; i++) {+ pm_module *mod;+ + mod = &pm_modules[i];+ printk(" %s %p\n", mod->modname, mod);+ mod->dev = new_au1xxx_power_device( mod->pmname, pm_catchall_callback, (void*)mod );+ if (mod->dev==NULL){printk("Error: Module Power Management failed to initialize \n");}+ /*Assigning Sleep State as current state*/+ mod->dev->cur_state=SLEEP_STATE;+ mod->dev->prev_state=AWAKE_STATE;+ }+ + return;+}+++/* The structures are layered so that there's an 'external' and an 'internal'+ * structure in the code. The external structure is really just the first+ * part of the internal structure so you can cast an internal structure as an+ * external structure and basically mask off the parts that should remain+ * internal to the driver. */-static int __init pm_init(void)+int au1xxx_pm_struct_init(void) {- register_sysctl_table(pm_dir_table, 1);- return 0;+ int i;+ static int initialized = 0;+ int retval = 0;++ /* check to see if structures are already initialized */+ if (initialized)+ return -EFAULT;+ else+ initialized = 1;++ spin_lock_irqsave(&au1xxx_pm_lock, spin_lock_flags);++ /* setup system device array */+ for (i = 0; i < MAX_SUPPORTED_DEVICES; i++) {+ sys_power_pointers[i] = &sys_power_array[i];+ strncpy(sys_power_pointers[i]->name, "NULL", strlen(""));+ sys_power_pointers[i]->callback = NULL;+ sys_power_pointers[i]->proc_entry = NULL;+ sys_power_pointers[i]->valid = 0;+ sys_power_pointers[i]->state_change_pending = 0;+ sys_power_pointers[i]->last_error = 0;+ sys_power_pointers[i]->cur_state = SLEEP_STATE;+ do_gettimeofday(&(sys_power_pointers[i]->cur_state_timestamp));+ sys_power_pointers[i]->prev_state = SLEEP_STATE;+ do_gettimeofday(&(sys_power_pointers[i]->prev_state_timestamp));+ sys_power_pointers[i]->data = NULL;+ sys_power_pointers[i]->timeout = 0;+ sys_power_pointers[i]->timer_proc_entry = NULL;+ }+ DPRINTK("sys_power_pointers array is now valid.\n");++ /* setup error array */+ for (i = 0; i < MAX_SUPPORTED_ERRORS; i++) {+ sys_error_pointers[i] = &sys_error_array[i];+ sys_error_pointers[i]->dev = NULL;+ sys_error_pointers[i]->error_code = 0;+ sys_error_pointers[i]->error_count = 0;+ sys_error_pointers[i]->first_timestamp = zero_timeval;+ sys_error_pointers[i]->last_timestamp = zero_timeval;+ }+ + /* setup the system device structure */+ system_dev->valid = 1;+ system_dev->state_change_pending = 0;+ system_dev->last_error = 0;+ strncpy(system_dev->name, "system", MAX_NAME_WIDTH);+ system_dev->callback = &system_power_callback;+ system_dev->cur_state = AWAKE_STATE;+ do_gettimeofday(&(system_dev->cur_state_timestamp));+ system_dev->proc_entry = NULL;+ system_dev->data = NULL;+ system_dev->timeout = SYSTEM_TIMEOUT;++ au1xxx_pm_setup->valid = 0;+ au1xxx_pm_setup->wakeup_mode = DEFAULT_WAKEUP;+ au1xxx_pm_setup->sleep_time = 0;+ au1xxx_pm_setup->feedback_mode = DEFAULT_FEEDBACK;++ zero_timeval.tv_sec = 0;+ zero_timeval.tv_usec = 0;++ spin_unlock_irqrestore(&au1xxx_pm_lock, spin_lock_flags);++ au1xxx_pm_debug();++ return retval; } -__initcall(pm_init);+static int au1xxx_pm_proc_init(void) {+ int i = 0;+ int retval = 0;+#if ENABLE_TEST_DEV+ au1xxx_power_dev_t *test_dev;+#endif + /* create power folder in /proc file system */+ DPRINTK("Attempting to create /proc/pm file system entires.\n");+ power_dir = proc_mkdir("pm", NULL);+ if (power_dir == NULL) {+ retval = -ENOMEM;+ goto no_power_dir;+ } else { DPRINTK("power_dir successfully created!\n"); }++ /* create the timeout folder in the /proc/pm/ directory */+ DPRINTK("Attempting to create /proc/pm file system entires.\n");+ timeout_dir = proc_mkdir("timeout", power_dir);+ if (timeout_dir == NULL) {+ retval = -ENOMEM;+ goto no_timeout_dir;+ } else { DPRINTK("timeout_dir successfully created!\n"); }++ spin_lock_irqsave(&au1xxx_pm_lock, spin_lock_flags);++ /* create the proc entry for both read and write for the system_dev */+ system_dev->proc_entry = create_proc_entry("system", 0644, power_dir);+ if (system_dev->proc_entry == NULL) {+ retval = -ENOMEM;+ goto no_system_power;+ }+ system_dev->proc_entry->data = system_dev;+ system_dev->proc_entry->read_proc = proc_read;+ system_dev->proc_entry->write_proc = proc_write;++ /* create the proc entry for both read and write for the settings */+ au1xxx_pm_setup->proc_entry = create_proc_entry("settings", 0644, power_dir);+ if (au1xxx_pm_setup->proc_entry == NULL) {+ retval = -ENOMEM;+ goto no_settings;+ }+ au1xxx_pm_setup->proc_entry->data = au1xxx_pm_setup;+ au1xxx_pm_setup->proc_entry->read_proc = proc_read_settings;+ au1xxx_pm_setup->proc_entry->write_proc = proc_write_settings;+ au1xxx_pm_setup->valid = 1;++ /* create the proc entry for read only for the pending entry */+ pending_proc_entry = create_proc_entry("pending", 0444, power_dir);+ if (pending_proc_entry == NULL) {+ retval = -ENOMEM;+ goto no_pending;+ }+ pending_proc_entry->read_proc = proc_read_pending; -/*- * This is right out of init/main.c- */+ /* create the proc entry for both read only for the error entry */+ error_proc_entry = create_proc_entry("error", 0444, power_dir);+ if (error_proc_entry == NULL) {+ retval = -ENOMEM;+ goto no_error;+ }+ error_proc_entry->data = first_error;+ error_proc_entry->read_proc = proc_read_error; -/* This is the number of bits of precision for the loops_per_jiffy. Each- bit takes on average 1.5/HZ seconds. This (like the original) is a little- better than 1% */-#define LPS_PREC 8--static void calibrate_delay(void)-{- unsigned long ticks, loopbit;- int lps_precision = LPS_PREC;-- loops_per_jiffy = (1 << 12);-- while (loops_per_jiffy <<= 1) {- /* wait for "start of" clock tick */- ticks = jiffies;- while (ticks == jiffies)- /* nothing */ ;- /* Go .. */- ticks = jiffies;- __delay(loops_per_jiffy);- ticks = jiffies - ticks;- if (ticks)- break;+ /* setup the proc entry for the devs that registered before proc_fs did */+ for (i = 0; i < MAX_SUPPORTED_DEVICES; i++) {+ if ((sys_power_pointers[i]->valid) && + (sys_power_pointers[i]->proc_entry == NULL))+ {+ sys_power_pointers[i]->proc_entry = create_proc_entry(+ sys_power_pointers[i]->name, + 0644, + power_dir);+ if (sys_power_pointers[i]->proc_entry == NULL) {+ retval = -ENOMEM;+ remove_au1xxx_power_device(sys_power_pointers[i]);+ return retval;+
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -