Перевод Linux Power Management Support | Версия для печати |
ключевые слова для поиска: драйвер управление питанием linux энергопотробление энергосбережение /* * Описание: Регистрация устройства в подсистеме управления питанием * * Параметры: * type - тип устройства (PCI-устройство, системное устройство, ...) * id - номер функционально независимой части устройства или уникальный * идентификатор * cback - обработчик запроса "обратного вызова" aka callback (засыпание, * возврат, ...) * * Возвращает: Зарегистрированное PM-устройство или NULL при ошибке * * Примеры: * dev = pm_register(PM_SYS_DEV, PM_SYS_VGA, vga_callback); * * struct pci_dev *pci_dev = pci_find_dev(...); * dev = pm_register(PM_PCI_DEV, PM_PCI_ID(pci_dev), callback); */ struct pm_dev *pm_register(pm_dev_t type, unsigned long id, pm_callback cback); /* * Описание: Исключает устройство из подсистемы управления питанием * * Параметры: * dev - PM-устройство, ранее возвращенное pm_register */ void pm_unregister(struct pm_dev *dev); /* * Описание: Исключает все устройства с указанным callback * * Параметры: * cback - ранее зарегистрированный callback * * Замечание: Используется для облегчения портирования со старого интерфейса APM */ void pm_unregister_all(pm_callback cback); /* * Обнаружение использования/простоя устройства * * В общем случае драйверы для всех устройств должны вызывать * pm_access перед обращением к оборудованию (т.е. перед чтением * или изменением аппаратных регистров). Пакетно-управляемые * или "запросные" драйверы должны дополнительно вызывать * pm_dev_idle в те моменты когда устройство не используется. * * Примеры: * 1) Клавиатурный драйвер должен вызывать pm_access при каждом нажатии * клавиши. * 2) Сетевой драйвер должен вызвать pm_access перед подтверждением * передачи или приема пакета и pm_dev_idle когда его очереди * передачи или приема пусты. * 3) VGA-драйвер должен вызывать pm_access перед обращением к регистрам * видеоконтроллера. * * В конечном счете, управляющий политикой PM использует информацию о доступе к * устройствам и их простое для принятия решений о "замораживании" отдельных * устройств или системы в целом. */ /* * Описание: Изменяет время последнего обращения к устройству и "будит" его при * необходимости. * * Параметры: * dev - PM-устройтво, возвращенное ранее pm_register * * Подробности: При вызове из обработчика прерывания pm_acces изменяет * время обращения к устройству, но не выполняет "подъема" устройства * (если устройство генерирует прерывания, то оно предполагается * работающим). Это важно и поэтому мы не сможем "будить" устройства * из обработчиков прерываний. */ void pm_access(struct pm_dev *dev); /* * Описание: Помечает устройство как простаивающее * * Параметры: * dev - PM-устройство, возвращенное ранее pm_register * * Подробности: Вызов pm_dev_idle может послужить сигналом управляющему * политикой "усыпить" устройство. Если запрос к новому устройству * будет получен между вызовом pm_dev_idle и "обратным вызовом" * pm_callback, то драйвер должен проигнорировать запрос pm_callback. */ void pm_dev_idle(struct pm_dev *dev); /* * Запрос "обратного вызова" управления питанием * * Параметры: * dev - PM-устройтво, возвращенное ранее pm_register * rqst - тип запроса * data - произвольные данные, связанные с запросом * * Возвращает: 0 при успешном выполнении запроса * EINVAL если запрос не поддерживатся * EBUSY если устройство сейчас занято и не может обработать запрос * ENOMEM если устройство не может обработать запрос из-за недостатка * памяти * * Подробности: callback запроса устройства будет вызван перед тем, как * устройство/система войдут в состояние "сна" (ACPI D1-D3) или * после того, как устройство/система будут "разбужены" (ACPI D0). * Для PM_SUSPEND введенное D-состояние ACPI будет передано в качестве * аргумента "data" callback'у. Драйвер устройства должен сохранить * (PM_SUSPEND) или восстановить (PM_RESUME) контекст устройства * когда будет получен запрос на вызов callback'а. * * После успешного выполнения запроса на "пробуждение" устройства * драйвер должен игнорировать любой доступ и запросы к оборудованию * до тех пор, пока не будет сделан вызов pm_access. */ typedef int (*pm_callback)(struct pm_dev *dev, pm_request_t rqst, void *data); Подробности ----------- Ниже приводится небольшой список ЧаВо, который будет со временем заменен полноценным руководством по написанию драйверов. В: Когда устройства "засыпают"? О: Устройства могут быть "усыплены" по прямому запросу пользователя (закрытие крышки ноутбука), из-за системной политики управления питанием (после 30 минут неактивности на консоли) или из-за политики управления питанием устройства (выключение питания устройства после 5 минут простоя). В: Должен ли драйвер всегда выполнять запрос на отключение питания? О: Нет, драйвер может вернуть -EBUSY в ответ на запрос и это остановит отключение питания системы. В этом случае все отключенные устройства "будятся" и система продолжает работать. Попытку можно повторить позже. В: Может ли драйвер блокировать запросы отключения/включения питания? О: Да, драйвер может задерживать выдачу ответа на такой запрос до готовности устройства обработать этот запрос. Однако лучше реагировать на запросы настолько быстро, насколько это возможно. В: В каком контексте порождаются запросы на отключение/включение? О: Запросы на отключение/питанию порождаются в контексте потока ядра. Поэтому во время "сна" системы неопасно блокировать и выделять память, инициировать запросы и делать все, что угодно, что можно делать по отношению к ядру. В: Будет ли драйвер обрабатывать запросы "во сне"? О: Возможно. Обработка запросов после "засыпания" целиком зависит от драйвера - он может как выполнять их, так и отбрасывать или просто игнорировать. Важно здесь то, что драйвер не получит доступа к устройству из-за того, что шина устройства может быть неактивна. (*) Если драйвер образует очередь из запросов к устройству в то время, пока оно "спит", то вам следует помнить о том, что состояние этого устройства и связанных с ним объектов (напр. локальной сети) к моменту пробуждения может измениться. Представляется разумным игнорировать все запросы, только если это не драйвер устройства хранения информации. В: Могу ли я управлять шинно-специфичными регистрами управления питанием? О: Нет. Этим занимается драйвер соответствующей шины. Этот драйвер или подсистема управления питанием в целом самостоятельно задействуют доступную функциональность по управлению питанием, если она имеется. В: Так что мне на самом деле необходимо для включения поддержки отключения/включения питания? О: Вам нужно сохранить любые данные о состоянии устройства (контекст), которые могут быть утеряны при отключении устройства. При использовании ACPI доступны три уровня отключения: D1, D2 и D3 (эти уровни передаются в качестве аргумента "data" callback'у устройства). На уровне D3 устройство отключается полностью и теряет весь контекст, D1 и D2 просто в разной степени понижают энергоптребление и в этом случае теряется только часть контекста. Чтобы просто и полностью обезопасить себя, достаточно просто сохранять весь контекст и потом полностью его восстанавливать. В: Где я могу сохранять контекст устройства? О: Скорее всего в памяти. Выделите буфер при помощи kmalloc или сохраните контекст в дескрипторе устройства. Это гарантирует, что содержимое памяти будет восстановлено и доступно перед включением, даже если система сбрасывала свое состояние диск перед отключением. В: Что мне нужно для использования ACPI по сранению с APM (и т.д.)? О: Драйверы не должны беспокоиться о том, какая технология управления питанием используется в системе. Для них гланое не забывать обрабатывать запросы на отключение/включение. В: Как быть с зависимостями между устройствами? О: Когда драйвер регистрирует устройство, подсистема управления питанием использует предоставленную информацию для построения дерева зависимостей между устройствами (вроде USB-устройство А подключено к USB-контроллеру Б, который подключен к PCI-шине В). Когда подсистема хочет "усыпить" устройство, она сначала посылает соответствующий запрос его драйверу, потому драйверу контроллера и так далее до системной шины. Во время пробуждения устройства все происходит в обратном порядке. В: Где я могу получить дополнительную информацию о включении управления питанием для моего особенного драйвера или устройства? О: Попробуйте обратиться в лист рассылки разработчиков ACPI acpi-devel@lists.sourceforge.net Системный интерфейс ------------------- Если вы разрабатываете новую систему управления питанием для Linux (что-то вроде APM или ACPI), то вам необходимо взаимодействовать с драйверами через существующий интерфейс управления питанием. /* * Посылает запрос отдельному устройству * * Параметры: * dev - PM-устройство, возвращенное ранее pm_register или pm_find * rqst - типа запроса * data - любые данные, связанные с запросом * * Возвращает: 0 при успешном выполнении запроса * См. описание pm_callback в случае возникновения ошибки * * Подробности: "Пробрасывает" запрос к callback'у устройства и, в случае * запроса на отключение/включение, присваивает соответствующее * значение полю "state" структуры pm_dev. */ int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data); /* * Посылает запрос всем устройствам * * Параметры: * rqst - тип запроса * data - любые данные, связанные с запросом * * Возвращает: 0 при успешном выполнении запроса * См. описание pm_callback в случае возникновения ошибки * * Подробности: Перебирает список зарегистрированных устройств и вызывает * pm_send для каждого пока не достигнет конца списка или * не возникнет ошибка. Если ошибка возникнет при запросе на * отключение, то возвращает все "пройденные" устройства в * состояние, в котором они были до этого. */ int pm_send_all(pm_request_t rqst, void *data); /* * Находит соответствующее устройство * * Параметры: * type - тип устройства (PCI-устройство, системное устройство или 0 для * выбора всех устройств) * from - предыдущее соответствие или NULL для запуска с начала * * Возвращает: Соотствествующее устройство или NULL, если ничего не найдено */ struct pm_dev *pm_find(pm_dev_t type, struct pm_dev *from); 3. Примечания В том же файле в дистрибутиве ядра 2.6.0 изменений не обнаружено. 4. Перевод San АНДРЕЕВ Опубликовал: San АНДРЕЕВ |