ubuntu 在 R40e 上 還有 Debian 在 Sempron 2600 上

2011年8月11日 星期四

LF - html mode 有作用嗎? 換兩行?
br
有效
pre:
大於符號 > . >
小魚 < . < 一起 <  > < >
code: 大於 > . > 小於 < . < 一起 < > > > 縮 排 也
option [1]1 [2] 2 1! 3 ads sss kkk
a
 b
   c

Suspend Test funtions in Kernel

Power manager options [*] Power Management Debug Support [*] Verbose Power Management debugging [*] Suspend to RAM and standby [*] Test suspend/resume and walealarm during bootup 上面幾個 option 打開。這樣 config 就會有 CONFIG_PM_DEBUG=y CONFIG_PM_VREBOSE=y CONFIG_PM_TEST_SUSPEND=y 這樣,在 kernel/power 下 main.c: static struct attribute * g[] = { &state_attr.attr, #ifdef CONFIG_PM_TRACE &pm_trace_attr.attr, #endif #ifdef CONFIG_SUSPEND_DEVICE_TIME_DEBUG &device_suspend_time_threshold_attr.attr, #endif #ifdef CONFIG_PM_SLEEP &pm_async_attr.attr, #ifdef CONFIG_PM_DEBUG &pm_test_attr.attr, #endif #ifdef CONFIG_USER_WAKELOCK &wake_lock_attr.attr, &wake_unlock_attr.attr, #endif #endif NULL, }; 可以看到每個 option 增加的 entry. CONFIG_PM_DEBUG,就會有 pm_test_attr 這個 entry 宣告的 pm_test_attr 有: #ifdef CONFIG_PM_DEBUG int pm_test_level = TEST_NONE; static const char * const pm_tests[__TEST_AFTER_LAST] = { [TEST_NONE] = "none", [TEST_CORE] = "core", [TEST_CPUS] = "processors", [TEST_PLATFORM] = "platform", [TEST_DEVICES] = "devices", [TEST_FREEZER] = "freezer", }; static ssize_t pm_test_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { char *s = buf; int level; for (level = TEST_FIRST; level <= TEST_MAX; level++) if (pm_tests[level]) { if (level == pm_test_level) s += sprintf(s, "[%s] ", pm_tests[level]); else s += sprintf(s, "%s ", pm_tests[level]); } if (s != buf) /* convert the last space to a newline */ *(s-1) = '\n'; return (s - buf); } static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) { const char * const *s; int level; char *p; int len; int error = -EINVAL; p = memchr(buf, '\n', n); len = p ? p - buf : n; mutex_lock(&pm_mutex); level = TEST_FIRST; for (s = &pm_tests[level]; level <= TEST_MAX; s++, level++) if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) { pm_test_level = level; error = 0; break; } mutex_unlock(&pm_mutex); return error ? error : n; } power_attr(pm_test); #endif /* CONFIG_PM_DEBUG */ 所以在 /sys/power 下會多一個 pm_test。 cat 出來會是 none core processors platform devices freezser 這個功能是用來測試 suspend/resume 的。 從 source code : kernel/power/suspend.c static int suspend_enter(suspend_state_t state) { ..... if (suspend_test(TEST_PLATFORM)) goto Platform_wake; error = disable_nonboot_cpus(); if (error || suspend_test(TEST_CPUS)) goto Enable_cpus; arch_suspend_disable_irqs(); BUG_ON(!irqs_disabled()); error = sysdev_suspend(PMSG_SUSPEND); if (!error) { if (!suspend_test(TEST_CORE)) error = suspend_ops->enter(state); sysdev_resume(); } ... 和 suspend_test( ) function : static int suspend_test(int level) { #ifdef CONFIG_PM_DEBUG if (pm_test_level == level) { printk(KERN_INFO "suspend debug: Waiting for 5 seconds.\n"); mdelay(5000); return 1; } #endif /* !CONFIG_PM_DEBUG */ return 0; } 可以看到, core, processors, platform, devices, freezer 各是不同的 suspend level。
利用 suspend_test( ) 可以讓 suspend 在不同 level 後 resume。

所以可以用來坐測試。

使用方法就是在 console 把要 test 的 level 寫入 /sys/power/pm_test 中。 #echo core > /sys/power/pm_test然後再 trigger suspend... 就會看到 suspend 後 5 sec 就自己 wakeup 了

2011年8月5日 星期五

mc13892 是給 embedded controller 用的 power controller。 支援 suspend mode 的操作。 支援的方式,是利用 hardware pin. 每一組 voltage output 都可以program 成: 1. always enable 2. depend on hardware in 3. off
ref: http://www.embeddeddesignindia.co.in/STATIC/PDF/200906/EDIOL_2009JUN22_CORE_AN_01.pdf?SOURCES=DOWNLOAD

http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MC13892&tab=Documentation_Tab&pspll=1&SelectedAsset=Documentation&ProdMetaId=PID/DC/MC13892&fromPSP=true&assetLockedForNavigation=true&componentId=2&leftNavCode=1&pageSize=25&Documentation=Documentation/00210KscRcb``Application%20Notes&fpsp=1&linkline=Application%20Notes

Editor : Geany : Change Editor's Color scheme

Geany Editor Window 的 color scheme 沒辦法在 Preference 中 設定。 要用設定檔的方式來作。 要改 color scheme: 1.Download 你要的 color scheme files. 2.放到 .config/geany/filedefs 這樣就可以。 他門是建議用 link 的方式來作,這樣就可以放很多 color scheme,然後用 ln -s 決定要用哪一個。
ref:
  1. http://code.google.com/p/geany-vibrant-ink-theme/wiki/HowToSetupVibrantInkTheme
  2. http://code.google.com/p/geany-dark-scheme/wiki/InstallGuide

kernel, suspend - pm.c : interface of module and kernel

在 commit log 中找與 suspend config 有關的 commit。 git log --grep="suspend" 找到 arch 裡的 pm.c

pm.c 好像是專屬的 power manager module,雖然結構跟一般的 module 一樣,device, driver 兩個,用
init, exit 插入 kernel symbol list。

但是在 init 時,使用的是 suspend_set_ops
implement 在 ./kernel/power/suspend.c static struct platform_suspend_ops *suspend_ops; void suspend_set_ops(struct platform_suspend_ops *ops) { mutex_lock(&pm_mutex); suspend_ops = ops; mutex_unlock(&pm_mutex); }
這個 structure 宣告在 include/linux/suspend.h struct platform_suspend_ops { int (*valid)(suspend_state_t state); int (*begin)(suspend_state_t state); int (*prepare)(void); int (*prepare_late)(void); int (*enter)(suspend_state_t state); void (*wake)(void); void (*finish)(void); void (*end)(void); void (*recover)(void); };
這個 suspend .c 很有趣,就是依照著 platform_suspend_ops 裡面的 function pointer,依照需要的時間來執行。 就是一個 kernel 的 interface 而已。

2011年8月4日 星期四

linux source : irq

include/linux/interrupt.h: extern int set_irq_wake(unsigned int irq, unsigned int on); static inline int enable_irq_wake(unsigned int irq) { return set_irq_wake(irq, 1); } static inline int disable_irq_wake(unsigned int irq) { return set_irq_wake(irq, 0); } 在 kernel/irq/manager.c: /** * set_irq_wake - control irq power management wakeup * @irq: interrupt to control * @on: enable/disable power management wakeup * * Enable/disable power management wakeup mode, which is * disabled by default. Enables and disables must match, * just as they match for non-wakeup mode support. * * Wakeup mode lets this IRQ wake the system from sleep * states like "suspend to RAM". */ int set_irq_wake(unsigned int irq, unsigned int on) { struct irq_desc *desc = irq_to_desc(irq); unsigned long flags; int ret = 0; /* wakeup-capable irqs can be shared between drivers that * don't need to have the same sleep mode behaviors. */ raw_spin_lock_irqsave(&desc->lock, flags); if (on) { if (desc->wake_depth++ == 0) { ret = set_irq_wake_real(irq, on); if (ret) desc->wake_depth = 0; else desc->status |= IRQ_WAKEUP; } } else { if (desc->wake_depth == 0) { WARN(1, "Unbalanced IRQ %d wake disable\n", irq); } else if (--desc->wake_depth == 0) { ret = set_irq_wake_real(irq, on); if (ret) desc->wake_depth = 1; else desc->status &= ~IRQ_WAKEUP; } } raw_spin_unlock_irqrestore(&desc->lock, flags); return ret; } 那個irq_to_desc,在 kernel/irq/handle.c. struct irq_desc *irq_to_desc(unsigned int irq) { return (irq < NR_IRQS) ? irq_desc + irq : NULL; } 那個 irq_desc 是宣告成: struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { [0 ... NR_IRQS-1] = { .status = IRQ_DISABLED, .chip = &no_irq_chip, .handle_irq = handle_bad_irq, .depth = 1, .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock), } }; 這個 irq_struct 宣告在 include/linux/irq.h /** * struct irq_desc - interrupt descriptor * @irq: interrupt number for this descriptor * @timer_rand_state: pointer to timer rand state struct * @kstat_irqs: irq stats per cpu * @irq_2_iommu: iommu with this irq * @handle_irq: highlevel irq-events handler [if NULL, __do_IRQ()] * @chip: low level interrupt hardware access * @msi_desc: MSI descriptor * @handler_data: per-IRQ data for the irq_chip methods * @chip_data: platform-specific per-chip private data for the chip * methods, to allow shared chip implementations * @action: the irq action chain * @status: status information * @depth: disable-depth, for nested irq_disable() calls * @wake_depth: enable depth, for multiple set_irq_wake() callers * @irq_count: stats field to detect stalled irqs * @last_unhandled: aging timer for unhandled count * @irqs_unhandled: stats field for spurious unhandled interrupts * @lock: locking for SMP * @affinity: IRQ affinity on SMP * @node: node index useful for balancing * @pending_mask: pending rebalanced interrupts * @threads_active: number of irqaction threads currently running * @wait_for_threads: wait queue for sync_irq to wait for threaded handlers * @dir: /proc/irq/ procfs entry * @name: flow handler name for /proc/interrupts output */ struct irq_desc { unsigned int irq; struct timer_rand_state *timer_rand_state; unsigned int *kstat_irqs; #ifdef CONFIG_INTR_REMAP struct irq_2_iommu *irq_2_iommu; #endif irq_flow_handler_t handle_irq; struct irq_chip *chip; struct msi_desc *msi_desc; void *handler_data; void *chip_data; struct irqaction *action; /* IRQ action list */ unsigned int status; /* IRQ status */ unsigned int depth; /* nested irq disables */ unsigned int wake_depth; /* nested wake enables */ unsigned int irq_count; /* For detecting broken IRQs */ unsigned long last_unhandled; /* Aging timer for unhandled count */ unsigned int irqs_unhandled; raw_spinlock_t lock; #ifdef CONFIG_SMP cpumask_var_t affinity; const struct cpumask *affinity_hint; unsigned int node; #ifdef CONFIG_GENERIC_PENDING_IRQ cpumask_var_t pending_mask; #endif #endif atomic_t threads_active; wait_queue_head_t wait_for_threads; #ifdef CONFIG_PROC_FS struct proc_dir_entry *dir; #endif const char *name; } ____cacheline_internodealigned_in_smp;

2011年8月2日 星期二

worklog - android atheros sd wifi

在 BoardConfig.mk 定義: WPA_SUPPLICANT_VERSION := VER_0_6_ATHEROS 然後在 external 下有三個 wpa_supplicant :
  1. wpa_supplicant
  2. wpa_supplicant_6
  3. wpa_supplicant_ath
都是 wpa_supplicant 的 source,但是由 WPA_SUPPLICANT_VERSION 決定要用哪一個
從 每個 folder 的 Android.mk 來看,開頭 ifeq ($(WPA_SUPPLICANT_VERSION),VER_0_5_X) 這樣決定
  1. wpa_supplicant : VER_0_5_X
  2. wpa_supplicant_6 : VER_0_6_X
  3. wpa_supplicant_ath : VER_0_6_ATHEROS
所以用的是 wpa_supplicant_ath


啟動 wifi

在 Setting - Wireless and networks 把Wi-Fi check 後。
package setting 下的 WifiEnabler.java : onPreferenceChange( ),有
int wifiApState = mWifiManager.getWifiApState(); ... if (mWifiManager.setWifiEnabled(enable)) { 其中的 mWifiManager 是 system service wrapper class: mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiManger 的 code: ./frameworks/base/wifi/java/android/net/wifi/WifiManager.java
之後 call 的 WifiManger.setWifiEnabled( ) : 只是一個 seriver 的包裝
public boolean setWifiEnabled(boolean enabled) { try { return mService.setWifiEnabled(enabled); } catch (RemoteException e) { return false; } } mService 是 IBinder interface : public WifiManager(IWifiManager service, Handler handler) { mService = service; mHandler = handler; } IWifiManager 是 (Binder interface): IWifiManager.aidl

IWifiManger 的 sponser server 是 WifiService : framework/android/server/WifiService: public class WifiService extends IWifiManager.Stub {
WifiService 的 setWifiEnabled() : sendEnableMessage(enable, true, Binder.getCallingUid()); sendEnableMessage() private void sendEnableMessage(boolean enable, boolean persist, int uid) { Message msg = Message.obtain(mWifiHandler, (enable ? MESSAGE_ENABLE_WIFI : MESSAGE_DISABLE_WIFI), (persist ? 1 : 0), uid); msg.sendToTarget(); } 這個 message 的 hanelder: public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_ENABLE_WIFI: setWifiEnabledBlocking(true, msg.arg1 == 1, msg.arg2); 所以是 setWifiEnabledBlocking : 這個做了 wifi driver loading, connect to wpa.. etc private boolean setWifiEnabledBlocking(boolean enable, boolean persist, int uid) { .... if (enable) { if (!mWifiStateTracker.loadDriver()) { Slog.e(TAG, "Failed to load Wi-Fi driver."); setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); return false; } if (!mWifiStateTracker.startSupplicant()) { mWifiStateTracker.unloadDriver(); Slog.e(TAG, "Failed to start supplicant daemon."); setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); return false; WifiStateTracker 在 framework/base/wifi ... public synchronized boolean loadDriver() { return WifiNative.loadDriver(); } call 到 jni : framework/base/core/jni/android_net_wifi_Wifi.cpp ,這只是 call 到 c code 的 wrapper。

實際 implement wifi_load_driver( ) 的在 : hardware/libhardware_legacy/wifi


wifi.c 的 wifi_load_driver 其實很普通,就是用 insmod load driver. if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) driver name, path, argument 都是寫在 Android.mk 裡: WIFI_DRIVER_MODULE_PATH := "/system/lib/modules/ar6000.ko" WIFI_DRIVER_MODULE_ARG := "" WIFI_DRIVER_MODULE_NAME := "ar6000"

標籤

網誌存檔