···2424# Power management related files2525acpi-y += wakeup.o2626acpi-$(CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT) += sleep.o2727-acpi-y += device_pm.o2727+acpi-y += device_sysfs.o device_pm.o2828acpi-$(CONFIG_ACPI_SLEEP) += proc.o29293030
+410-1
drivers/acpi/bus.c
···423423 acpi_evaluate_ost(handle, type, ost_code, NULL);424424}425425426426+static void acpi_device_notify(acpi_handle handle, u32 event, void *data)427427+{428428+ struct acpi_device *device = data;429429+430430+ device->driver->ops.notify(device, event);431431+}432432+433433+static void acpi_device_notify_fixed(void *data)434434+{435435+ struct acpi_device *device = data;436436+437437+ /* Fixed hardware devices have no handles */438438+ acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device);439439+}440440+441441+static u32 acpi_device_fixed_event(void *data)442442+{443443+ acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_device_notify_fixed, data);444444+ return ACPI_INTERRUPT_HANDLED;445445+}446446+447447+static int acpi_device_install_notify_handler(struct acpi_device *device)448448+{449449+ acpi_status status;450450+451451+ if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)452452+ status =453453+ acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,454454+ acpi_device_fixed_event,455455+ device);456456+ else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)457457+ status =458458+ acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,459459+ acpi_device_fixed_event,460460+ device);461461+ else462462+ status = acpi_install_notify_handler(device->handle,463463+ ACPI_DEVICE_NOTIFY,464464+ acpi_device_notify,465465+ device);466466+467467+ if (ACPI_FAILURE(status))468468+ return -EINVAL;469469+ return 0;470470+}471471+472472+static void acpi_device_remove_notify_handler(struct acpi_device *device)473473+{474474+ if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)475475+ acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,476476+ acpi_device_fixed_event);477477+ else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)478478+ acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,479479+ acpi_device_fixed_event);480480+ else481481+ acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,482482+ acpi_device_notify);483483+}484484+485485+/* --------------------------------------------------------------------------486486+ Device Matching487487+ -------------------------------------------------------------------------- */488488+489489+/**490490+ * acpi_device_is_first_physical_node - Is given dev first physical node491491+ * @adev: ACPI companion device492492+ * @dev: Physical device to check493493+ *494494+ * Function checks if given @dev is the first physical devices attached to495495+ * the ACPI companion device. This distinction is needed in some cases496496+ * where the same companion device is shared between many physical devices.497497+ *498498+ * Note that the caller have to provide valid @adev pointer.499499+ */500500+bool acpi_device_is_first_physical_node(struct acpi_device *adev,501501+ const struct device *dev)502502+{503503+ bool ret = false;504504+505505+ mutex_lock(&adev->physical_node_lock);506506+ if (!list_empty(&adev->physical_node_list)) {507507+ const struct acpi_device_physical_node *node;508508+509509+ node = list_first_entry(&adev->physical_node_list,510510+ struct acpi_device_physical_node, node);511511+ ret = node->dev == dev;512512+ }513513+ mutex_unlock(&adev->physical_node_lock);514514+515515+ return ret;516516+}517517+518518+/*519519+ * acpi_companion_match() - Can we match via ACPI companion device520520+ * @dev: Device in question521521+ *522522+ * Check if the given device has an ACPI companion and if that companion has523523+ * a valid list of PNP IDs, and if the device is the first (primary) physical524524+ * device associated with it. Return the companion pointer if that's the case525525+ * or NULL otherwise.526526+ *527527+ * If multiple physical devices are attached to a single ACPI companion, we need528528+ * to be careful. The usage scenario for this kind of relationship is that all529529+ * of the physical devices in question use resources provided by the ACPI530530+ * companion. A typical case is an MFD device where all the sub-devices share531531+ * the parent's ACPI companion. In such cases we can only allow the primary532532+ * (first) physical device to be matched with the help of the companion's PNP533533+ * IDs.534534+ *535535+ * Additional physical devices sharing the ACPI companion can still use536536+ * resources available from it but they will be matched normally using functions537537+ * provided by their bus types (and analogously for their modalias).538538+ */539539+struct acpi_device *acpi_companion_match(const struct device *dev)540540+{541541+ struct acpi_device *adev;542542+ struct mutex *physical_node_lock;543543+544544+ adev = ACPI_COMPANION(dev);545545+ if (!adev)546546+ return NULL;547547+548548+ if (list_empty(&adev->pnp.ids))549549+ return NULL;550550+551551+ physical_node_lock = &adev->physical_node_lock;552552+ mutex_lock(physical_node_lock);553553+ if (list_empty(&adev->physical_node_list)) {554554+ adev = NULL;555555+ } else {556556+ const struct acpi_device_physical_node *node;557557+558558+ node = list_first_entry(&adev->physical_node_list,559559+ struct acpi_device_physical_node, node);560560+ if (node->dev != dev)561561+ adev = NULL;562562+ }563563+ mutex_unlock(physical_node_lock);564564+565565+ return adev;566566+}567567+568568+/**569569+ * acpi_of_match_device - Match device object using the "compatible" property.570570+ * @adev: ACPI device object to match.571571+ * @of_match_table: List of device IDs to match against.572572+ *573573+ * If @dev has an ACPI companion which has ACPI_DT_NAMESPACE_HID in its list of574574+ * identifiers and a _DSD object with the "compatible" property, use that575575+ * property to match against the given list of identifiers.576576+ */577577+static bool acpi_of_match_device(struct acpi_device *adev,578578+ const struct of_device_id *of_match_table)579579+{580580+ const union acpi_object *of_compatible, *obj;581581+ int i, nval;582582+583583+ if (!adev)584584+ return false;585585+586586+ of_compatible = adev->data.of_compatible;587587+ if (!of_match_table || !of_compatible)588588+ return false;589589+590590+ if (of_compatible->type == ACPI_TYPE_PACKAGE) {591591+ nval = of_compatible->package.count;592592+ obj = of_compatible->package.elements;593593+ } else { /* Must be ACPI_TYPE_STRING. */594594+ nval = 1;595595+ obj = of_compatible;596596+ }597597+ /* Now we can look for the driver DT compatible strings */598598+ for (i = 0; i < nval; i++, obj++) {599599+ const struct of_device_id *id;600600+601601+ for (id = of_match_table; id->compatible[0]; id++)602602+ if (!strcasecmp(obj->string.pointer, id->compatible))603603+ return true;604604+ }605605+606606+ return false;607607+}608608+609609+static bool __acpi_match_device_cls(const struct acpi_device_id *id,610610+ struct acpi_hardware_id *hwid)611611+{612612+ int i, msk, byte_shift;613613+ char buf[3];614614+615615+ if (!id->cls)616616+ return false;617617+618618+ /* Apply class-code bitmask, before checking each class-code byte */619619+ for (i = 1; i <= 3; i++) {620620+ byte_shift = 8 * (3 - i);621621+ msk = (id->cls_msk >> byte_shift) & 0xFF;622622+ if (!msk)623623+ continue;624624+625625+ sprintf(buf, "%02x", (id->cls >> byte_shift) & msk);626626+ if (strncmp(buf, &hwid->id[(i - 1) * 2], 2))627627+ return false;628628+ }629629+ return true;630630+}631631+632632+static const struct acpi_device_id *__acpi_match_device(633633+ struct acpi_device *device,634634+ const struct acpi_device_id *ids,635635+ const struct of_device_id *of_ids)636636+{637637+ const struct acpi_device_id *id;638638+ struct acpi_hardware_id *hwid;639639+640640+ /*641641+ * If the device is not present, it is unnecessary to load device642642+ * driver for it.643643+ */644644+ if (!device || !device->status.present)645645+ return NULL;646646+647647+ list_for_each_entry(hwid, &device->pnp.ids, list) {648648+ /* First, check the ACPI/PNP IDs provided by the caller. */649649+ for (id = ids; id->id[0] || id->cls; id++) {650650+ if (id->id[0] && !strcmp((char *) id->id, hwid->id))651651+ return id;652652+ else if (id->cls && __acpi_match_device_cls(id, hwid))653653+ return id;654654+ }655655+656656+ /*657657+ * Next, check ACPI_DT_NAMESPACE_HID and try to match the658658+ * "compatible" property if found.659659+ *660660+ * The id returned by the below is not valid, but the only661661+ * caller passing non-NULL of_ids here is only interested in662662+ * whether or not the return value is NULL.663663+ */664664+ if (!strcmp(ACPI_DT_NAMESPACE_HID, hwid->id)665665+ && acpi_of_match_device(device, of_ids))666666+ return id;667667+ }668668+ return NULL;669669+}670670+671671+/**672672+ * acpi_match_device - Match a struct device against a given list of ACPI IDs673673+ * @ids: Array of struct acpi_device_id object to match against.674674+ * @dev: The device structure to match.675675+ *676676+ * Check if @dev has a valid ACPI handle and if there is a struct acpi_device677677+ * object for that handle and use that object to match against a given list of678678+ * device IDs.679679+ *680680+ * Return a pointer to the first matching ID on success or %NULL on failure.681681+ */682682+const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,683683+ const struct device *dev)684684+{685685+ return __acpi_match_device(acpi_companion_match(dev), ids, NULL);686686+}687687+EXPORT_SYMBOL_GPL(acpi_match_device);688688+689689+int acpi_match_device_ids(struct acpi_device *device,690690+ const struct acpi_device_id *ids)691691+{692692+ return __acpi_match_device(device, ids, NULL) ? 0 : -ENOENT;693693+}694694+EXPORT_SYMBOL(acpi_match_device_ids);695695+696696+bool acpi_driver_match_device(struct device *dev,697697+ const struct device_driver *drv)698698+{699699+ if (!drv->acpi_match_table)700700+ return acpi_of_match_device(ACPI_COMPANION(dev),701701+ drv->of_match_table);702702+703703+ return !!__acpi_match_device(acpi_companion_match(dev),704704+ drv->acpi_match_table, drv->of_match_table);705705+}706706+EXPORT_SYMBOL_GPL(acpi_driver_match_device);707707+708708+/* --------------------------------------------------------------------------709709+ ACPI Driver Management710710+ -------------------------------------------------------------------------- */711711+712712+/**713713+ * acpi_bus_register_driver - register a driver with the ACPI bus714714+ * @driver: driver being registered715715+ *716716+ * Registers a driver with the ACPI bus. Searches the namespace for all717717+ * devices that match the driver's criteria and binds. Returns zero for718718+ * success or a negative error status for failure.719719+ */720720+int acpi_bus_register_driver(struct acpi_driver *driver)721721+{722722+ int ret;723723+724724+ if (acpi_disabled)725725+ return -ENODEV;726726+ driver->drv.name = driver->name;727727+ driver->drv.bus = &acpi_bus_type;728728+ driver->drv.owner = driver->owner;729729+730730+ ret = driver_register(&driver->drv);731731+ return ret;732732+}733733+734734+EXPORT_SYMBOL(acpi_bus_register_driver);735735+736736+/**737737+ * acpi_bus_unregister_driver - unregisters a driver with the ACPI bus738738+ * @driver: driver to unregister739739+ *740740+ * Unregisters a driver with the ACPI bus. Searches the namespace for all741741+ * devices that match the driver's criteria and unbinds.742742+ */743743+void acpi_bus_unregister_driver(struct acpi_driver *driver)744744+{745745+ driver_unregister(&driver->drv);746746+}747747+748748+EXPORT_SYMBOL(acpi_bus_unregister_driver);749749+750750+/* --------------------------------------------------------------------------751751+ ACPI Bus operations752752+ -------------------------------------------------------------------------- */753753+754754+static int acpi_bus_match(struct device *dev, struct device_driver *drv)755755+{756756+ struct acpi_device *acpi_dev = to_acpi_device(dev);757757+ struct acpi_driver *acpi_drv = to_acpi_driver(drv);758758+759759+ return acpi_dev->flags.match_driver760760+ && !acpi_match_device_ids(acpi_dev, acpi_drv->ids);761761+}762762+763763+static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)764764+{765765+ return __acpi_device_uevent_modalias(to_acpi_device(dev), env);766766+}767767+768768+static int acpi_device_probe(struct device *dev)769769+{770770+ struct acpi_device *acpi_dev = to_acpi_device(dev);771771+ struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver);772772+ int ret;773773+774774+ if (acpi_dev->handler && !acpi_is_pnp_device(acpi_dev))775775+ return -EINVAL;776776+777777+ if (!acpi_drv->ops.add)778778+ return -ENOSYS;779779+780780+ ret = acpi_drv->ops.add(acpi_dev);781781+ if (ret)782782+ return ret;783783+784784+ acpi_dev->driver = acpi_drv;785785+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,786786+ "Driver [%s] successfully bound to device [%s]\n",787787+ acpi_drv->name, acpi_dev->pnp.bus_id));788788+789789+ if (acpi_drv->ops.notify) {790790+ ret = acpi_device_install_notify_handler(acpi_dev);791791+ if (ret) {792792+ if (acpi_drv->ops.remove)793793+ acpi_drv->ops.remove(acpi_dev);794794+795795+ acpi_dev->driver = NULL;796796+ acpi_dev->driver_data = NULL;797797+ return ret;798798+ }799799+ }800800+801801+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",802802+ acpi_drv->name, acpi_dev->pnp.bus_id));803803+ get_device(dev);804804+ return 0;805805+}806806+807807+static int acpi_device_remove(struct device * dev)808808+{809809+ struct acpi_device *acpi_dev = to_acpi_device(dev);810810+ struct acpi_driver *acpi_drv = acpi_dev->driver;811811+812812+ if (acpi_drv) {813813+ if (acpi_drv->ops.notify)814814+ acpi_device_remove_notify_handler(acpi_dev);815815+ if (acpi_drv->ops.remove)816816+ acpi_drv->ops.remove(acpi_dev);817817+ }818818+ acpi_dev->driver = NULL;819819+ acpi_dev->driver_data = NULL;820820+821821+ put_device(dev);822822+ return 0;823823+}824824+825825+struct bus_type acpi_bus_type = {826826+ .name = "acpi",827827+ .match = acpi_bus_match,828828+ .probe = acpi_device_probe,829829+ .remove = acpi_device_remove,830830+ .uevent = acpi_device_uevent,831831+};832832+426833/* --------------------------------------------------------------------------427834 Initialization/Cleanup428835 -------------------------------------------------------------------------- */···1068661 */1069662 acpi_root_dir = proc_mkdir(ACPI_BUS_FILE_ROOT, NULL);107066310711071- return 0;664664+ result = bus_register(&acpi_bus_type);665665+ if (!result)666666+ return 0;10726671073668 /* Mimic structured exception handling */1074669 error1:
+8
drivers/acpi/device_pm.c
···11231123 if (dev->pm_domain)11241124 return -EEXIST;1125112511261126+ /*11271127+ * Only attach the power domain to the first device if the11281128+ * companion is shared by multiple. This is to prevent doing power11291129+ * management twice.11301130+ */11311131+ if (!acpi_device_is_first_physical_node(adev, dev))11321132+ return -EBUSY;11331133+11261134 acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func);11271135 dev->pm_domain = &acpi_general_pm_domain;11281136 if (power_on) {
+521
drivers/acpi/device_sysfs.c
···11+/*22+ * drivers/acpi/device_sysfs.c - ACPI device sysfs attributes and modalias.33+ *44+ * Copyright (C) 2015, Intel Corp.55+ * Author: Mika Westerberg <mika.westerberg@linux.intel.com>66+ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>77+ *88+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~99+ *1010+ * This program is free software; you can redistribute it and/or modify1111+ * it under the terms of the GNU General Public License version 2 as published1212+ * by the Free Software Foundation.1313+ *1414+ * This program is distributed in the hope that it will be useful, but1515+ * WITHOUT ANY WARRANTY; without even the implied warranty of1616+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU1717+ * General Public License for more details.1818+ *1919+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~2020+ */2121+2222+#include <linux/acpi.h>2323+#include <linux/device.h>2424+#include <linux/export.h>2525+#include <linux/nls.h>2626+2727+#include "internal.h"2828+2929+/**3030+ * create_pnp_modalias - Create hid/cid(s) string for modalias and uevent3131+ * @acpi_dev: ACPI device object.3232+ * @modalias: Buffer to print into.3333+ * @size: Size of the buffer.3434+ *3535+ * Creates hid/cid(s) string needed for modalias and uevent3636+ * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:3737+ * char *modalias: "acpi:IBM0001:ACPI0001"3838+ * Return: 0: no _HID and no _CID3939+ * -EINVAL: output error4040+ * -ENOMEM: output is truncated4141+*/4242+static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias,4343+ int size)4444+{4545+ int len;4646+ int count;4747+ struct acpi_hardware_id *id;4848+4949+ /*5050+ * Since we skip ACPI_DT_NAMESPACE_HID from the modalias below, 0 should5151+ * be returned if ACPI_DT_NAMESPACE_HID is the only ACPI/PNP ID in the5252+ * device's list.5353+ */5454+ count = 0;5555+ list_for_each_entry(id, &acpi_dev->pnp.ids, list)5656+ if (strcmp(id->id, ACPI_DT_NAMESPACE_HID))5757+ count++;5858+5959+ if (!count)6060+ return 0;6161+6262+ len = snprintf(modalias, size, "acpi:");6363+ if (len <= 0)6464+ return len;6565+6666+ size -= len;6767+6868+ list_for_each_entry(id, &acpi_dev->pnp.ids, list) {6969+ if (!strcmp(id->id, ACPI_DT_NAMESPACE_HID))7070+ continue;7171+7272+ count = snprintf(&modalias[len], size, "%s:", id->id);7373+ if (count < 0)7474+ return -EINVAL;7575+7676+ if (count >= size)7777+ return -ENOMEM;7878+7979+ len += count;8080+ size -= count;8181+ }8282+ modalias[len] = '\0';8383+ return len;8484+}8585+8686+/**8787+ * create_of_modalias - Creates DT compatible string for modalias and uevent8888+ * @acpi_dev: ACPI device object.8989+ * @modalias: Buffer to print into.9090+ * @size: Size of the buffer.9191+ *9292+ * Expose DT compatible modalias as of:NnameTCcompatible. This function should9393+ * only be called for devices having ACPI_DT_NAMESPACE_HID in their list of9494+ * ACPI/PNP IDs.9595+ */9696+static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias,9797+ int size)9898+{9999+ struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };100100+ const union acpi_object *of_compatible, *obj;101101+ int len, count;102102+ int i, nval;103103+ char *c;104104+105105+ acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);106106+ /* DT strings are all in lower case */107107+ for (c = buf.pointer; *c != '\0'; c++)108108+ *c = tolower(*c);109109+110110+ len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);111111+ ACPI_FREE(buf.pointer);112112+113113+ if (len <= 0)114114+ return len;115115+116116+ of_compatible = acpi_dev->data.of_compatible;117117+ if (of_compatible->type == ACPI_TYPE_PACKAGE) {118118+ nval = of_compatible->package.count;119119+ obj = of_compatible->package.elements;120120+ } else { /* Must be ACPI_TYPE_STRING. */121121+ nval = 1;122122+ obj = of_compatible;123123+ }124124+ for (i = 0; i < nval; i++, obj++) {125125+ count = snprintf(&modalias[len], size, "C%s",126126+ obj->string.pointer);127127+ if (count < 0)128128+ return -EINVAL;129129+130130+ if (count >= size)131131+ return -ENOMEM;132132+133133+ len += count;134134+ size -= count;135135+ }136136+ modalias[len] = '\0';137137+ return len;138138+}139139+140140+int __acpi_device_uevent_modalias(struct acpi_device *adev,141141+ struct kobj_uevent_env *env)142142+{143143+ int len;144144+145145+ if (!adev)146146+ return -ENODEV;147147+148148+ if (list_empty(&adev->pnp.ids))149149+ return 0;150150+151151+ if (add_uevent_var(env, "MODALIAS="))152152+ return -ENOMEM;153153+154154+ len = create_pnp_modalias(adev, &env->buf[env->buflen - 1],155155+ sizeof(env->buf) - env->buflen);156156+ if (len < 0)157157+ return len;158158+159159+ env->buflen += len;160160+ if (!adev->data.of_compatible)161161+ return 0;162162+163163+ if (len > 0 && add_uevent_var(env, "MODALIAS="))164164+ return -ENOMEM;165165+166166+ len = create_of_modalias(adev, &env->buf[env->buflen - 1],167167+ sizeof(env->buf) - env->buflen);168168+ if (len < 0)169169+ return len;170170+171171+ env->buflen += len;172172+173173+ return 0;174174+}175175+176176+/**177177+ * acpi_device_uevent_modalias - uevent modalias for ACPI-enumerated devices.178178+ *179179+ * Create the uevent modalias field for ACPI-enumerated devices.180180+ *181181+ * Because other buses do not support ACPI HIDs & CIDs, e.g. for a device with182182+ * hid:IBM0001 and cid:ACPI0001 you get: "acpi:IBM0001:ACPI0001".183183+ */184184+int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)185185+{186186+ return __acpi_device_uevent_modalias(acpi_companion_match(dev), env);187187+}188188+EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias);189189+190190+static int __acpi_device_modalias(struct acpi_device *adev, char *buf, int size)191191+{192192+ int len, count;193193+194194+ if (!adev)195195+ return -ENODEV;196196+197197+ if (list_empty(&adev->pnp.ids))198198+ return 0;199199+200200+ len = create_pnp_modalias(adev, buf, size - 1);201201+ if (len < 0) {202202+ return len;203203+ } else if (len > 0) {204204+ buf[len++] = '\n';205205+ size -= len;206206+ }207207+ if (!adev->data.of_compatible)208208+ return len;209209+210210+ count = create_of_modalias(adev, buf + len, size - 1);211211+ if (count < 0) {212212+ return count;213213+ } else if (count > 0) {214214+ len += count;215215+ buf[len++] = '\n';216216+ }217217+218218+ return len;219219+}220220+221221+/**222222+ * acpi_device_modalias - modalias sysfs attribute for ACPI-enumerated devices.223223+ *224224+ * Create the modalias sysfs attribute for ACPI-enumerated devices.225225+ *226226+ * Because other buses do not support ACPI HIDs & CIDs, e.g. for a device with227227+ * hid:IBM0001 and cid:ACPI0001 you get: "acpi:IBM0001:ACPI0001".228228+ */229229+int acpi_device_modalias(struct device *dev, char *buf, int size)230230+{231231+ return __acpi_device_modalias(acpi_companion_match(dev), buf, size);232232+}233233+EXPORT_SYMBOL_GPL(acpi_device_modalias);234234+235235+static ssize_t236236+acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) {237237+ return __acpi_device_modalias(to_acpi_device(dev), buf, 1024);238238+}239239+static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);240240+241241+static ssize_t real_power_state_show(struct device *dev,242242+ struct device_attribute *attr, char *buf)243243+{244244+ struct acpi_device *adev = to_acpi_device(dev);245245+ int state;246246+ int ret;247247+248248+ ret = acpi_device_get_power(adev, &state);249249+ if (ret)250250+ return ret;251251+252252+ return sprintf(buf, "%s\n", acpi_power_state_string(state));253253+}254254+255255+static DEVICE_ATTR(real_power_state, 0444, real_power_state_show, NULL);256256+257257+static ssize_t power_state_show(struct device *dev,258258+ struct device_attribute *attr, char *buf)259259+{260260+ struct acpi_device *adev = to_acpi_device(dev);261261+262262+ return sprintf(buf, "%s\n", acpi_power_state_string(adev->power.state));263263+}264264+265265+static DEVICE_ATTR(power_state, 0444, power_state_show, NULL);266266+267267+static ssize_t268268+acpi_eject_store(struct device *d, struct device_attribute *attr,269269+ const char *buf, size_t count)270270+{271271+ struct acpi_device *acpi_device = to_acpi_device(d);272272+ acpi_object_type not_used;273273+ acpi_status status;274274+275275+ if (!count || buf[0] != '1')276276+ return -EINVAL;277277+278278+ if ((!acpi_device->handler || !acpi_device->handler->hotplug.enabled)279279+ && !acpi_device->driver)280280+ return -ENODEV;281281+282282+ status = acpi_get_type(acpi_device->handle, ¬_used);283283+ if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)284284+ return -ENODEV;285285+286286+ get_device(&acpi_device->dev);287287+ status = acpi_hotplug_schedule(acpi_device, ACPI_OST_EC_OSPM_EJECT);288288+ if (ACPI_SUCCESS(status))289289+ return count;290290+291291+ put_device(&acpi_device->dev);292292+ acpi_evaluate_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,293293+ ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);294294+ return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;295295+}296296+297297+static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);298298+299299+static ssize_t300300+acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf) {301301+ struct acpi_device *acpi_dev = to_acpi_device(dev);302302+303303+ return sprintf(buf, "%s\n", acpi_device_hid(acpi_dev));304304+}305305+static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);306306+307307+static ssize_t acpi_device_uid_show(struct device *dev,308308+ struct device_attribute *attr, char *buf)309309+{310310+ struct acpi_device *acpi_dev = to_acpi_device(dev);311311+312312+ return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);313313+}314314+static DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL);315315+316316+static ssize_t acpi_device_adr_show(struct device *dev,317317+ struct device_attribute *attr, char *buf)318318+{319319+ struct acpi_device *acpi_dev = to_acpi_device(dev);320320+321321+ return sprintf(buf, "0x%08x\n",322322+ (unsigned int)(acpi_dev->pnp.bus_address));323323+}324324+static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL);325325+326326+static ssize_t327327+acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) {328328+ struct acpi_device *acpi_dev = to_acpi_device(dev);329329+ struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};330330+ int result;331331+332332+ result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path);333333+ if (result)334334+ goto end;335335+336336+ result = sprintf(buf, "%s\n", (char*)path.pointer);337337+ kfree(path.pointer);338338+end:339339+ return result;340340+}341341+static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL);342342+343343+/* sysfs file that shows description text from the ACPI _STR method */344344+static ssize_t description_show(struct device *dev,345345+ struct device_attribute *attr,346346+ char *buf) {347347+ struct acpi_device *acpi_dev = to_acpi_device(dev);348348+ int result;349349+350350+ if (acpi_dev->pnp.str_obj == NULL)351351+ return 0;352352+353353+ /*354354+ * The _STR object contains a Unicode identifier for a device.355355+ * We need to convert to utf-8 so it can be displayed.356356+ */357357+ result = utf16s_to_utf8s(358358+ (wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer,359359+ acpi_dev->pnp.str_obj->buffer.length,360360+ UTF16_LITTLE_ENDIAN, buf,361361+ PAGE_SIZE);362362+363363+ buf[result++] = '\n';364364+365365+ return result;366366+}367367+static DEVICE_ATTR(description, 0444, description_show, NULL);368368+369369+static ssize_t370370+acpi_device_sun_show(struct device *dev, struct device_attribute *attr,371371+ char *buf) {372372+ struct acpi_device *acpi_dev = to_acpi_device(dev);373373+ acpi_status status;374374+ unsigned long long sun;375375+376376+ status = acpi_evaluate_integer(acpi_dev->handle, "_SUN", NULL, &sun);377377+ if (ACPI_FAILURE(status))378378+ return -ENODEV;379379+380380+ return sprintf(buf, "%llu\n", sun);381381+}382382+static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL);383383+384384+static ssize_t status_show(struct device *dev, struct device_attribute *attr,385385+ char *buf) {386386+ struct acpi_device *acpi_dev = to_acpi_device(dev);387387+ acpi_status status;388388+ unsigned long long sta;389389+390390+ status = acpi_evaluate_integer(acpi_dev->handle, "_STA", NULL, &sta);391391+ if (ACPI_FAILURE(status))392392+ return -ENODEV;393393+394394+ return sprintf(buf, "%llu\n", sta);395395+}396396+static DEVICE_ATTR_RO(status);397397+398398+/**399399+ * acpi_device_setup_files - Create sysfs attributes of an ACPI device.400400+ * @dev: ACPI device object.401401+ */402402+int acpi_device_setup_files(struct acpi_device *dev)403403+{404404+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};405405+ acpi_status status;406406+ int result = 0;407407+408408+ /*409409+ * Devices gotten from FADT don't have a "path" attribute410410+ */411411+ if (dev->handle) {412412+ result = device_create_file(&dev->dev, &dev_attr_path);413413+ if (result)414414+ goto end;415415+ }416416+417417+ if (!list_empty(&dev->pnp.ids)) {418418+ result = device_create_file(&dev->dev, &dev_attr_hid);419419+ if (result)420420+ goto end;421421+422422+ result = device_create_file(&dev->dev, &dev_attr_modalias);423423+ if (result)424424+ goto end;425425+ }426426+427427+ /*428428+ * If device has _STR, 'description' file is created429429+ */430430+ if (acpi_has_method(dev->handle, "_STR")) {431431+ status = acpi_evaluate_object(dev->handle, "_STR",432432+ NULL, &buffer);433433+ if (ACPI_FAILURE(status))434434+ buffer.pointer = NULL;435435+ dev->pnp.str_obj = buffer.pointer;436436+ result = device_create_file(&dev->dev, &dev_attr_description);437437+ if (result)438438+ goto end;439439+ }440440+441441+ if (dev->pnp.type.bus_address)442442+ result = device_create_file(&dev->dev, &dev_attr_adr);443443+ if (dev->pnp.unique_id)444444+ result = device_create_file(&dev->dev, &dev_attr_uid);445445+446446+ if (acpi_has_method(dev->handle, "_SUN")) {447447+ result = device_create_file(&dev->dev, &dev_attr_sun);448448+ if (result)449449+ goto end;450450+ }451451+452452+ if (acpi_has_method(dev->handle, "_STA")) {453453+ result = device_create_file(&dev->dev, &dev_attr_status);454454+ if (result)455455+ goto end;456456+ }457457+458458+ /*459459+ * If device has _EJ0, 'eject' file is created that is used to trigger460460+ * hot-removal function from userland.461461+ */462462+ if (acpi_has_method(dev->handle, "_EJ0")) {463463+ result = device_create_file(&dev->dev, &dev_attr_eject);464464+ if (result)465465+ return result;466466+ }467467+468468+ if (dev->flags.power_manageable) {469469+ result = device_create_file(&dev->dev, &dev_attr_power_state);470470+ if (result)471471+ return result;472472+473473+ if (dev->power.flags.power_resources)474474+ result = device_create_file(&dev->dev,475475+ &dev_attr_real_power_state);476476+ }477477+478478+end:479479+ return result;480480+}481481+482482+/**483483+ * acpi_device_remove_files - Remove sysfs attributes of an ACPI device.484484+ * @dev: ACPI device object.485485+ */486486+void acpi_device_remove_files(struct acpi_device *dev)487487+{488488+ if (dev->flags.power_manageable) {489489+ device_remove_file(&dev->dev, &dev_attr_power_state);490490+ if (dev->power.flags.power_resources)491491+ device_remove_file(&dev->dev,492492+ &dev_attr_real_power_state);493493+ }494494+495495+ /*496496+ * If device has _STR, remove 'description' file497497+ */498498+ if (acpi_has_method(dev->handle, "_STR")) {499499+ kfree(dev->pnp.str_obj);500500+ device_remove_file(&dev->dev, &dev_attr_description);501501+ }502502+ /*503503+ * If device has _EJ0, remove 'eject' file.504504+ */505505+ if (acpi_has_method(dev->handle, "_EJ0"))506506+ device_remove_file(&dev->dev, &dev_attr_eject);507507+508508+ if (acpi_has_method(dev->handle, "_SUN"))509509+ device_remove_file(&dev->dev, &dev_attr_sun);510510+511511+ if (dev->pnp.unique_id)512512+ device_remove_file(&dev->dev, &dev_attr_uid);513513+ if (dev->pnp.type.bus_address)514514+ device_remove_file(&dev->dev, &dev_attr_adr);515515+ device_remove_file(&dev->dev, &dev_attr_modalias);516516+ device_remove_file(&dev->dev, &dev_attr_hid);517517+ if (acpi_has_method(dev->handle, "_STA"))518518+ device_remove_file(&dev->dev, &dev_attr_status);519519+ if (dev->handle)520520+ device_remove_file(&dev->dev, &dev_attr_path);521521+}
···11/*22- * acpi_power.c - ACPI Bus Power Management ($Revision: 39 $)22+ * drivers/acpi/power.c - ACPI Power Resources management.33 *44- * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>55- * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>44+ * Copyright (C) 2001 - 2015 Intel Corp.55+ * Author: Andy Grover <andrew.grover@intel.com>66+ * Author: Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>77+ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>68 *79 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~810 *···2927 * ACPI power-managed devices may be controlled in two ways:3028 * 1. via "Device Specific (D-State) Control"3129 * 2. via "Power Resource Control".3232- * This module is used to manage devices relying on Power Resource Control.3030+ * The code below deals with ACPI Power Resources control.3331 * 3434- * An ACPI "power resource object" describes a software controllable power3535- * plane, clock plane, or other resource used by a power managed device.3232+ * An ACPI "power resource object" represents a software controllable power3333+ * plane, clock plane, or other resource depended on by a device.3434+ *3635 * A device may rely on multiple power resources, and a power resource3736 * may be shared by multiple devices.3837 */
-860
drivers/acpi/scan.c
···115115 return 0;116116}117117118118-/**119119- * create_pnp_modalias - Create hid/cid(s) string for modalias and uevent120120- * @acpi_dev: ACPI device object.121121- * @modalias: Buffer to print into.122122- * @size: Size of the buffer.123123- *124124- * Creates hid/cid(s) string needed for modalias and uevent125125- * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:126126- * char *modalias: "acpi:IBM0001:ACPI0001"127127- * Return: 0: no _HID and no _CID128128- * -EINVAL: output error129129- * -ENOMEM: output is truncated130130-*/131131-static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias,132132- int size)133133-{134134- int len;135135- int count;136136- struct acpi_hardware_id *id;137137-138138- /*139139- * Since we skip ACPI_DT_NAMESPACE_HID from the modalias below, 0 should140140- * be returned if ACPI_DT_NAMESPACE_HID is the only ACPI/PNP ID in the141141- * device's list.142142- */143143- count = 0;144144- list_for_each_entry(id, &acpi_dev->pnp.ids, list)145145- if (strcmp(id->id, ACPI_DT_NAMESPACE_HID))146146- count++;147147-148148- if (!count)149149- return 0;150150-151151- len = snprintf(modalias, size, "acpi:");152152- if (len <= 0)153153- return len;154154-155155- size -= len;156156-157157- list_for_each_entry(id, &acpi_dev->pnp.ids, list) {158158- if (!strcmp(id->id, ACPI_DT_NAMESPACE_HID))159159- continue;160160-161161- count = snprintf(&modalias[len], size, "%s:", id->id);162162- if (count < 0)163163- return -EINVAL;164164-165165- if (count >= size)166166- return -ENOMEM;167167-168168- len += count;169169- size -= count;170170- }171171- modalias[len] = '\0';172172- return len;173173-}174174-175175-/**176176- * create_of_modalias - Creates DT compatible string for modalias and uevent177177- * @acpi_dev: ACPI device object.178178- * @modalias: Buffer to print into.179179- * @size: Size of the buffer.180180- *181181- * Expose DT compatible modalias as of:NnameTCcompatible. This function should182182- * only be called for devices having ACPI_DT_NAMESPACE_HID in their list of183183- * ACPI/PNP IDs.184184- */185185-static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias,186186- int size)187187-{188188- struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };189189- const union acpi_object *of_compatible, *obj;190190- int len, count;191191- int i, nval;192192- char *c;193193-194194- acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);195195- /* DT strings are all in lower case */196196- for (c = buf.pointer; *c != '\0'; c++)197197- *c = tolower(*c);198198-199199- len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);200200- ACPI_FREE(buf.pointer);201201-202202- if (len <= 0)203203- return len;204204-205205- of_compatible = acpi_dev->data.of_compatible;206206- if (of_compatible->type == ACPI_TYPE_PACKAGE) {207207- nval = of_compatible->package.count;208208- obj = of_compatible->package.elements;209209- } else { /* Must be ACPI_TYPE_STRING. */210210- nval = 1;211211- obj = of_compatible;212212- }213213- for (i = 0; i < nval; i++, obj++) {214214- count = snprintf(&modalias[len], size, "C%s",215215- obj->string.pointer);216216- if (count < 0)217217- return -EINVAL;218218-219219- if (count >= size)220220- return -ENOMEM;221221-222222- len += count;223223- size -= count;224224- }225225- modalias[len] = '\0';226226- return len;227227-}228228-229229-/*230230- * acpi_companion_match() - Can we match via ACPI companion device231231- * @dev: Device in question232232- *233233- * Check if the given device has an ACPI companion and if that companion has234234- * a valid list of PNP IDs, and if the device is the first (primary) physical235235- * device associated with it. Return the companion pointer if that's the case236236- * or NULL otherwise.237237- *238238- * If multiple physical devices are attached to a single ACPI companion, we need239239- * to be careful. The usage scenario for this kind of relationship is that all240240- * of the physical devices in question use resources provided by the ACPI241241- * companion. A typical case is an MFD device where all the sub-devices share242242- * the parent's ACPI companion. In such cases we can only allow the primary243243- * (first) physical device to be matched with the help of the companion's PNP244244- * IDs.245245- *246246- * Additional physical devices sharing the ACPI companion can still use247247- * resources available from it but they will be matched normally using functions248248- * provided by their bus types (and analogously for their modalias).249249- */250250-static struct acpi_device *acpi_companion_match(const struct device *dev)251251-{252252- struct acpi_device *adev;253253- struct mutex *physical_node_lock;254254-255255- adev = ACPI_COMPANION(dev);256256- if (!adev)257257- return NULL;258258-259259- if (list_empty(&adev->pnp.ids))260260- return NULL;261261-262262- physical_node_lock = &adev->physical_node_lock;263263- mutex_lock(physical_node_lock);264264- if (list_empty(&adev->physical_node_list)) {265265- adev = NULL;266266- } else {267267- const struct acpi_device_physical_node *node;268268-269269- node = list_first_entry(&adev->physical_node_list,270270- struct acpi_device_physical_node, node);271271- if (node->dev != dev)272272- adev = NULL;273273- }274274- mutex_unlock(physical_node_lock);275275-276276- return adev;277277-}278278-279279-static int __acpi_device_uevent_modalias(struct acpi_device *adev,280280- struct kobj_uevent_env *env)281281-{282282- int len;283283-284284- if (!adev)285285- return -ENODEV;286286-287287- if (list_empty(&adev->pnp.ids))288288- return 0;289289-290290- if (add_uevent_var(env, "MODALIAS="))291291- return -ENOMEM;292292-293293- len = create_pnp_modalias(adev, &env->buf[env->buflen - 1],294294- sizeof(env->buf) - env->buflen);295295- if (len < 0)296296- return len;297297-298298- env->buflen += len;299299- if (!adev->data.of_compatible)300300- return 0;301301-302302- if (len > 0 && add_uevent_var(env, "MODALIAS="))303303- return -ENOMEM;304304-305305- len = create_of_modalias(adev, &env->buf[env->buflen - 1],306306- sizeof(env->buf) - env->buflen);307307- if (len < 0)308308- return len;309309-310310- env->buflen += len;311311-312312- return 0;313313-}314314-315315-/*316316- * Creates uevent modalias field for ACPI enumerated devices.317317- * Because the other buses does not support ACPI HIDs & CIDs.318318- * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get:319319- * "acpi:IBM0001:ACPI0001"320320- */321321-int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)322322-{323323- return __acpi_device_uevent_modalias(acpi_companion_match(dev), env);324324-}325325-EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias);326326-327327-static int __acpi_device_modalias(struct acpi_device *adev, char *buf, int size)328328-{329329- int len, count;330330-331331- if (!adev)332332- return -ENODEV;333333-334334- if (list_empty(&adev->pnp.ids))335335- return 0;336336-337337- len = create_pnp_modalias(adev, buf, size - 1);338338- if (len < 0) {339339- return len;340340- } else if (len > 0) {341341- buf[len++] = '\n';342342- size -= len;343343- }344344- if (!adev->data.of_compatible)345345- return len;346346-347347- count = create_of_modalias(adev, buf + len, size - 1);348348- if (count < 0) {349349- return count;350350- } else if (count > 0) {351351- len += count;352352- buf[len++] = '\n';353353- }354354-355355- return len;356356-}357357-358358-/*359359- * Creates modalias sysfs attribute for ACPI enumerated devices.360360- * Because the other buses does not support ACPI HIDs & CIDs.361361- * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get:362362- * "acpi:IBM0001:ACPI0001"363363- */364364-int acpi_device_modalias(struct device *dev, char *buf, int size)365365-{366366- return __acpi_device_modalias(acpi_companion_match(dev), buf, size);367367-}368368-EXPORT_SYMBOL_GPL(acpi_device_modalias);369369-370370-static ssize_t371371-acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) {372372- return __acpi_device_modalias(to_acpi_device(dev), buf, 1024);373373-}374374-static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);375375-376118bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent)377119{378120 struct acpi_device_physical_node *pn;···443701 unlock_device_hotplug();444702}445703446446-static ssize_t real_power_state_show(struct device *dev,447447- struct device_attribute *attr, char *buf)448448-{449449- struct acpi_device *adev = to_acpi_device(dev);450450- int state;451451- int ret;452452-453453- ret = acpi_device_get_power(adev, &state);454454- if (ret)455455- return ret;456456-457457- return sprintf(buf, "%s\n", acpi_power_state_string(state));458458-}459459-460460-static DEVICE_ATTR(real_power_state, 0444, real_power_state_show, NULL);461461-462462-static ssize_t power_state_show(struct device *dev,463463- struct device_attribute *attr, char *buf)464464-{465465- struct acpi_device *adev = to_acpi_device(dev);466466-467467- return sprintf(buf, "%s\n", acpi_power_state_string(adev->power.state));468468-}469469-470470-static DEVICE_ATTR(power_state, 0444, power_state_show, NULL);471471-472472-static ssize_t473473-acpi_eject_store(struct device *d, struct device_attribute *attr,474474- const char *buf, size_t count)475475-{476476- struct acpi_device *acpi_device = to_acpi_device(d);477477- acpi_object_type not_used;478478- acpi_status status;479479-480480- if (!count || buf[0] != '1')481481- return -EINVAL;482482-483483- if ((!acpi_device->handler || !acpi_device->handler->hotplug.enabled)484484- && !acpi_device->driver)485485- return -ENODEV;486486-487487- status = acpi_get_type(acpi_device->handle, ¬_used);488488- if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)489489- return -ENODEV;490490-491491- get_device(&acpi_device->dev);492492- status = acpi_hotplug_schedule(acpi_device, ACPI_OST_EC_OSPM_EJECT);493493- if (ACPI_SUCCESS(status))494494- return count;495495-496496- put_device(&acpi_device->dev);497497- acpi_evaluate_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,498498- ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);499499- return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;500500-}501501-502502-static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);503503-504504-static ssize_t505505-acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf) {506506- struct acpi_device *acpi_dev = to_acpi_device(dev);507507-508508- return sprintf(buf, "%s\n", acpi_device_hid(acpi_dev));509509-}510510-static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);511511-512512-static ssize_t acpi_device_uid_show(struct device *dev,513513- struct device_attribute *attr, char *buf)514514-{515515- struct acpi_device *acpi_dev = to_acpi_device(dev);516516-517517- return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);518518-}519519-static DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL);520520-521521-static ssize_t acpi_device_adr_show(struct device *dev,522522- struct device_attribute *attr, char *buf)523523-{524524- struct acpi_device *acpi_dev = to_acpi_device(dev);525525-526526- return sprintf(buf, "0x%08x\n",527527- (unsigned int)(acpi_dev->pnp.bus_address));528528-}529529-static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL);530530-531531-static ssize_t532532-acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) {533533- struct acpi_device *acpi_dev = to_acpi_device(dev);534534- struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};535535- int result;536536-537537- result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path);538538- if (result)539539- goto end;540540-541541- result = sprintf(buf, "%s\n", (char*)path.pointer);542542- kfree(path.pointer);543543-end:544544- return result;545545-}546546-static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL);547547-548548-/* sysfs file that shows description text from the ACPI _STR method */549549-static ssize_t description_show(struct device *dev,550550- struct device_attribute *attr,551551- char *buf) {552552- struct acpi_device *acpi_dev = to_acpi_device(dev);553553- int result;554554-555555- if (acpi_dev->pnp.str_obj == NULL)556556- return 0;557557-558558- /*559559- * The _STR object contains a Unicode identifier for a device.560560- * We need to convert to utf-8 so it can be displayed.561561- */562562- result = utf16s_to_utf8s(563563- (wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer,564564- acpi_dev->pnp.str_obj->buffer.length,565565- UTF16_LITTLE_ENDIAN, buf,566566- PAGE_SIZE);567567-568568- buf[result++] = '\n';569569-570570- return result;571571-}572572-static DEVICE_ATTR(description, 0444, description_show, NULL);573573-574574-static ssize_t575575-acpi_device_sun_show(struct device *dev, struct device_attribute *attr,576576- char *buf) {577577- struct acpi_device *acpi_dev = to_acpi_device(dev);578578- acpi_status status;579579- unsigned long long sun;580580-581581- status = acpi_evaluate_integer(acpi_dev->handle, "_SUN", NULL, &sun);582582- if (ACPI_FAILURE(status))583583- return -ENODEV;584584-585585- return sprintf(buf, "%llu\n", sun);586586-}587587-static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL);588588-589589-static ssize_t status_show(struct device *dev, struct device_attribute *attr,590590- char *buf) {591591- struct acpi_device *acpi_dev = to_acpi_device(dev);592592- acpi_status status;593593- unsigned long long sta;594594-595595- status = acpi_evaluate_integer(acpi_dev->handle, "_STA", NULL, &sta);596596- if (ACPI_FAILURE(status))597597- return -ENODEV;598598-599599- return sprintf(buf, "%llu\n", sta);600600-}601601-static DEVICE_ATTR_RO(status);602602-603603-static int acpi_device_setup_files(struct acpi_device *dev)604604-{605605- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};606606- acpi_status status;607607- int result = 0;608608-609609- /*610610- * Devices gotten from FADT don't have a "path" attribute611611- */612612- if (dev->handle) {613613- result = device_create_file(&dev->dev, &dev_attr_path);614614- if (result)615615- goto end;616616- }617617-618618- if (!list_empty(&dev->pnp.ids)) {619619- result = device_create_file(&dev->dev, &dev_attr_hid);620620- if (result)621621- goto end;622622-623623- result = device_create_file(&dev->dev, &dev_attr_modalias);624624- if (result)625625- goto end;626626- }627627-628628- /*629629- * If device has _STR, 'description' file is created630630- */631631- if (acpi_has_method(dev->handle, "_STR")) {632632- status = acpi_evaluate_object(dev->handle, "_STR",633633- NULL, &buffer);634634- if (ACPI_FAILURE(status))635635- buffer.pointer = NULL;636636- dev->pnp.str_obj = buffer.pointer;637637- result = device_create_file(&dev->dev, &dev_attr_description);638638- if (result)639639- goto end;640640- }641641-642642- if (dev->pnp.type.bus_address)643643- result = device_create_file(&dev->dev, &dev_attr_adr);644644- if (dev->pnp.unique_id)645645- result = device_create_file(&dev->dev, &dev_attr_uid);646646-647647- if (acpi_has_method(dev->handle, "_SUN")) {648648- result = device_create_file(&dev->dev, &dev_attr_sun);649649- if (result)650650- goto end;651651- }652652-653653- if (acpi_has_method(dev->handle, "_STA")) {654654- result = device_create_file(&dev->dev, &dev_attr_status);655655- if (result)656656- goto end;657657- }658658-659659- /*660660- * If device has _EJ0, 'eject' file is created that is used to trigger661661- * hot-removal function from userland.662662- */663663- if (acpi_has_method(dev->handle, "_EJ0")) {664664- result = device_create_file(&dev->dev, &dev_attr_eject);665665- if (result)666666- return result;667667- }668668-669669- if (dev->flags.power_manageable) {670670- result = device_create_file(&dev->dev, &dev_attr_power_state);671671- if (result)672672- return result;673673-674674- if (dev->power.flags.power_resources)675675- result = device_create_file(&dev->dev,676676- &dev_attr_real_power_state);677677- }678678-679679-end:680680- return result;681681-}682682-683683-static void acpi_device_remove_files(struct acpi_device *dev)684684-{685685- if (dev->flags.power_manageable) {686686- device_remove_file(&dev->dev, &dev_attr_power_state);687687- if (dev->power.flags.power_resources)688688- device_remove_file(&dev->dev,689689- &dev_attr_real_power_state);690690- }691691-692692- /*693693- * If device has _STR, remove 'description' file694694- */695695- if (acpi_has_method(dev->handle, "_STR")) {696696- kfree(dev->pnp.str_obj);697697- device_remove_file(&dev->dev, &dev_attr_description);698698- }699699- /*700700- * If device has _EJ0, remove 'eject' file.701701- */702702- if (acpi_has_method(dev->handle, "_EJ0"))703703- device_remove_file(&dev->dev, &dev_attr_eject);704704-705705- if (acpi_has_method(dev->handle, "_SUN"))706706- device_remove_file(&dev->dev, &dev_attr_sun);707707-708708- if (dev->pnp.unique_id)709709- device_remove_file(&dev->dev, &dev_attr_uid);710710- if (dev->pnp.type.bus_address)711711- device_remove_file(&dev->dev, &dev_attr_adr);712712- device_remove_file(&dev->dev, &dev_attr_modalias);713713- device_remove_file(&dev->dev, &dev_attr_hid);714714- if (acpi_has_method(dev->handle, "_STA"))715715- device_remove_file(&dev->dev, &dev_attr_status);716716- if (dev->handle)717717- device_remove_file(&dev->dev, &dev_attr_path);718718-}719719-/* --------------------------------------------------------------------------720720- ACPI Bus operations721721- -------------------------------------------------------------------------- */722722-723723-/**724724- * acpi_of_match_device - Match device object using the "compatible" property.725725- * @adev: ACPI device object to match.726726- * @of_match_table: List of device IDs to match against.727727- *728728- * If @dev has an ACPI companion which has ACPI_DT_NAMESPACE_HID in its list of729729- * identifiers and a _DSD object with the "compatible" property, use that730730- * property to match against the given list of identifiers.731731- */732732-static bool acpi_of_match_device(struct acpi_device *adev,733733- const struct of_device_id *of_match_table)734734-{735735- const union acpi_object *of_compatible, *obj;736736- int i, nval;737737-738738- if (!adev)739739- return false;740740-741741- of_compatible = adev->data.of_compatible;742742- if (!of_match_table || !of_compatible)743743- return false;744744-745745- if (of_compatible->type == ACPI_TYPE_PACKAGE) {746746- nval = of_compatible->package.count;747747- obj = of_compatible->package.elements;748748- } else { /* Must be ACPI_TYPE_STRING. */749749- nval = 1;750750- obj = of_compatible;751751- }752752- /* Now we can look for the driver DT compatible strings */753753- for (i = 0; i < nval; i++, obj++) {754754- const struct of_device_id *id;755755-756756- for (id = of_match_table; id->compatible[0]; id++)757757- if (!strcasecmp(obj->string.pointer, id->compatible))758758- return true;759759- }760760-761761- return false;762762-}763763-764764-static bool __acpi_match_device_cls(const struct acpi_device_id *id,765765- struct acpi_hardware_id *hwid)766766-{767767- int i, msk, byte_shift;768768- char buf[3];769769-770770- if (!id->cls)771771- return false;772772-773773- /* Apply class-code bitmask, before checking each class-code byte */774774- for (i = 1; i <= 3; i++) {775775- byte_shift = 8 * (3 - i);776776- msk = (id->cls_msk >> byte_shift) & 0xFF;777777- if (!msk)778778- continue;779779-780780- sprintf(buf, "%02x", (id->cls >> byte_shift) & msk);781781- if (strncmp(buf, &hwid->id[(i - 1) * 2], 2))782782- return false;783783- }784784- return true;785785-}786786-787787-static const struct acpi_device_id *__acpi_match_device(788788- struct acpi_device *device,789789- const struct acpi_device_id *ids,790790- const struct of_device_id *of_ids)791791-{792792- const struct acpi_device_id *id;793793- struct acpi_hardware_id *hwid;794794-795795- /*796796- * If the device is not present, it is unnecessary to load device797797- * driver for it.798798- */799799- if (!device || !device->status.present)800800- return NULL;801801-802802- list_for_each_entry(hwid, &device->pnp.ids, list) {803803- /* First, check the ACPI/PNP IDs provided by the caller. */804804- for (id = ids; id->id[0] || id->cls; id++) {805805- if (id->id[0] && !strcmp((char *) id->id, hwid->id))806806- return id;807807- else if (id->cls && __acpi_match_device_cls(id, hwid))808808- return id;809809- }810810-811811- /*812812- * Next, check ACPI_DT_NAMESPACE_HID and try to match the813813- * "compatible" property if found.814814- *815815- * The id returned by the below is not valid, but the only816816- * caller passing non-NULL of_ids here is only interested in817817- * whether or not the return value is NULL.818818- */819819- if (!strcmp(ACPI_DT_NAMESPACE_HID, hwid->id)820820- && acpi_of_match_device(device, of_ids))821821- return id;822822- }823823- return NULL;824824-}825825-826826-/**827827- * acpi_match_device - Match a struct device against a given list of ACPI IDs828828- * @ids: Array of struct acpi_device_id object to match against.829829- * @dev: The device structure to match.830830- *831831- * Check if @dev has a valid ACPI handle and if there is a struct acpi_device832832- * object for that handle and use that object to match against a given list of833833- * device IDs.834834- *835835- * Return a pointer to the first matching ID on success or %NULL on failure.836836- */837837-const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,838838- const struct device *dev)839839-{840840- return __acpi_match_device(acpi_companion_match(dev), ids, NULL);841841-}842842-EXPORT_SYMBOL_GPL(acpi_match_device);843843-844844-int acpi_match_device_ids(struct acpi_device *device,845845- const struct acpi_device_id *ids)846846-{847847- return __acpi_match_device(device, ids, NULL) ? 0 : -ENOENT;848848-}849849-EXPORT_SYMBOL(acpi_match_device_ids);850850-851851-bool acpi_driver_match_device(struct device *dev,852852- const struct device_driver *drv)853853-{854854- if (!drv->acpi_match_table)855855- return acpi_of_match_device(ACPI_COMPANION(dev),856856- drv->of_match_table);857857-858858- return !!__acpi_match_device(acpi_companion_match(dev),859859- drv->acpi_match_table, drv->of_match_table);860860-}861861-EXPORT_SYMBOL_GPL(acpi_driver_match_device);862862-863704static void acpi_free_power_resources_lists(struct acpi_device *device)864705{865706 int i;···4681143 acpi_free_power_resources_lists(acpi_dev);4691144 kfree(acpi_dev);4701145}471471-472472-static int acpi_bus_match(struct device *dev, struct device_driver *drv)473473-{474474- struct acpi_device *acpi_dev = to_acpi_device(dev);475475- struct acpi_driver *acpi_drv = to_acpi_driver(drv);476476-477477- return acpi_dev->flags.match_driver478478- && !acpi_match_device_ids(acpi_dev, acpi_drv->ids);479479-}480480-481481-static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)482482-{483483- return __acpi_device_uevent_modalias(to_acpi_device(dev), env);484484-}485485-486486-static void acpi_device_notify(acpi_handle handle, u32 event, void *data)487487-{488488- struct acpi_device *device = data;489489-490490- device->driver->ops.notify(device, event);491491-}492492-493493-static void acpi_device_notify_fixed(void *data)494494-{495495- struct acpi_device *device = data;496496-497497- /* Fixed hardware devices have no handles */498498- acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device);499499-}500500-501501-static u32 acpi_device_fixed_event(void *data)502502-{503503- acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_device_notify_fixed, data);504504- return ACPI_INTERRUPT_HANDLED;505505-}506506-507507-static int acpi_device_install_notify_handler(struct acpi_device *device)508508-{509509- acpi_status status;510510-511511- if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)512512- status =513513- acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,514514- acpi_device_fixed_event,515515- device);516516- else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)517517- status =518518- acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,519519- acpi_device_fixed_event,520520- device);521521- else522522- status = acpi_install_notify_handler(device->handle,523523- ACPI_DEVICE_NOTIFY,524524- acpi_device_notify,525525- device);526526-527527- if (ACPI_FAILURE(status))528528- return -EINVAL;529529- return 0;530530-}531531-532532-static void acpi_device_remove_notify_handler(struct acpi_device *device)533533-{534534- if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)535535- acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,536536- acpi_device_fixed_event);537537- else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)538538- acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,539539- acpi_device_fixed_event);540540- else541541- acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,542542- acpi_device_notify);543543-}544544-545545-static int acpi_device_probe(struct device *dev)546546-{547547- struct acpi_device *acpi_dev = to_acpi_device(dev);548548- struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver);549549- int ret;550550-551551- if (acpi_dev->handler && !acpi_is_pnp_device(acpi_dev))552552- return -EINVAL;553553-554554- if (!acpi_drv->ops.add)555555- return -ENOSYS;556556-557557- ret = acpi_drv->ops.add(acpi_dev);558558- if (ret)559559- return ret;560560-561561- acpi_dev->driver = acpi_drv;562562- ACPI_DEBUG_PRINT((ACPI_DB_INFO,563563- "Driver [%s] successfully bound to device [%s]\n",564564- acpi_drv->name, acpi_dev->pnp.bus_id));565565-566566- if (acpi_drv->ops.notify) {567567- ret = acpi_device_install_notify_handler(acpi_dev);568568- if (ret) {569569- if (acpi_drv->ops.remove)570570- acpi_drv->ops.remove(acpi_dev);571571-572572- acpi_dev->driver = NULL;573573- acpi_dev->driver_data = NULL;574574- return ret;575575- }576576- }577577-578578- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",579579- acpi_drv->name, acpi_dev->pnp.bus_id));580580- get_device(dev);581581- return 0;582582-}583583-584584-static int acpi_device_remove(struct device * dev)585585-{586586- struct acpi_device *acpi_dev = to_acpi_device(dev);587587- struct acpi_driver *acpi_drv = acpi_dev->driver;588588-589589- if (acpi_drv) {590590- if (acpi_drv->ops.notify)591591- acpi_device_remove_notify_handler(acpi_dev);592592- if (acpi_drv->ops.remove)593593- acpi_drv->ops.remove(acpi_dev);594594- }595595- acpi_dev->driver = NULL;596596- acpi_dev->driver_data = NULL;597597-598598- put_device(dev);599599- return 0;600600-}601601-602602-struct bus_type acpi_bus_type = {603603- .name = "acpi",604604- .match = acpi_bus_match,605605- .probe = acpi_device_probe,606606- .remove = acpi_device_remove,607607- .uevent = acpi_device_uevent,608608-};60911466101147static void acpi_device_del(struct acpi_device *device)6111148{···7141527 next = child->node.next;7151528 return next == head ? NULL : list_entry(next, struct acpi_device, node);7161529}717717-718718-/* --------------------------------------------------------------------------719719- Driver Management720720- -------------------------------------------------------------------------- */721721-/**722722- * acpi_bus_register_driver - register a driver with the ACPI bus723723- * @driver: driver being registered724724- *725725- * Registers a driver with the ACPI bus. Searches the namespace for all726726- * devices that match the driver's criteria and binds. Returns zero for727727- * success or a negative error status for failure.728728- */729729-int acpi_bus_register_driver(struct acpi_driver *driver)730730-{731731- int ret;732732-733733- if (acpi_disabled)734734- return -ENODEV;735735- driver->drv.name = driver->name;736736- driver->drv.bus = &acpi_bus_type;737737- driver->drv.owner = driver->owner;738738-739739- ret = driver_register(&driver->drv);740740- return ret;741741-}742742-743743-EXPORT_SYMBOL(acpi_bus_register_driver);744744-745745-/**746746- * acpi_bus_unregister_driver - unregisters a driver with the ACPI bus747747- * @driver: driver to unregister748748- *749749- * Unregisters a driver with the ACPI bus. Searches the namespace for all750750- * devices that match the driver's criteria and unbinds.751751- */752752-void acpi_bus_unregister_driver(struct acpi_driver *driver)753753-{754754- driver_unregister(&driver->drv);755755-}756756-757757-EXPORT_SYMBOL(acpi_bus_unregister_driver);75815307591531/* --------------------------------------------------------------------------7601532 Device Enumeration···18892743int __init acpi_scan_init(void)18902744{18912745 int result;18921892-18931893- result = bus_register(&acpi_bus_type);18941894- if (result) {18951895- /* We don't want to quit even if we failed to add suspend/resume */18961896- printk(KERN_ERR PREFIX "Could not register bus type\n");18971897- }1898274618992747 acpi_pci_root_init();19002748 acpi_pci_link_init();
+43
drivers/base/core.c
···12521252}12531253EXPORT_SYMBOL_GPL(device_unregister);1254125412551255+static struct device *prev_device(struct klist_iter *i)12561256+{12571257+ struct klist_node *n = klist_prev(i);12581258+ struct device *dev = NULL;12591259+ struct device_private *p;12601260+12611261+ if (n) {12621262+ p = to_device_private_parent(n);12631263+ dev = p->device;12641264+ }12651265+ return dev;12661266+}12671267+12551268static struct device *next_device(struct klist_iter *i)12561269{12571270 struct klist_node *n = klist_next(i);···13521339 return error;13531340}13541341EXPORT_SYMBOL_GPL(device_for_each_child);13421342+13431343+/**13441344+ * device_for_each_child_reverse - device child iterator in reversed order.13451345+ * @parent: parent struct device.13461346+ * @fn: function to be called for each device.13471347+ * @data: data for the callback.13481348+ *13491349+ * Iterate over @parent's child devices, and call @fn for each,13501350+ * passing it @data.13511351+ *13521352+ * We check the return of @fn each time. If it returns anything13531353+ * other than 0, we break out and return that value.13541354+ */13551355+int device_for_each_child_reverse(struct device *parent, void *data,13561356+ int (*fn)(struct device *dev, void *data))13571357+{13581358+ struct klist_iter i;13591359+ struct device *child;13601360+ int error = 0;13611361+13621362+ if (!parent->p)13631363+ return 0;13641364+13651365+ klist_iter_init(&parent->p->klist_children, &i);13661366+ while ((child = prev_device(&i)) && !error)13671367+ error = fn(child, data);13681368+ klist_iter_exit(&i);13691369+ return error;13701370+}13711371+EXPORT_SYMBOL_GPL(device_for_each_child_reverse);1355137213561373/**13571374 * device_find_child - device iterator for locating a particular device.
+20
drivers/base/dd.c
···399399 *400400 * This function must be called with @dev lock held. When called for a401401 * USB interface, @dev->parent lock must be held as well.402402+ *403403+ * If the device has a parent, runtime-resume the parent before driver probing.402404 */403405int driver_probe_device(struct device_driver *drv, struct device *dev)404406{···412410 pr_debug("bus: '%s': %s: matched device %s with driver %s\n",413411 drv->bus->name, __func__, dev_name(dev), drv->name);414412413413+ if (dev->parent)414414+ pm_runtime_get_sync(dev->parent);415415+415416 pm_runtime_barrier(dev);416417 ret = really_probe(dev, drv);417418 pm_request_idle(dev);419419+420420+ if (dev->parent)421421+ pm_runtime_put(dev->parent);418422419423 return ret;420424}···515507516508 device_lock(dev);517509510510+ if (dev->parent)511511+ pm_runtime_get_sync(dev->parent);512512+518513 bus_for_each_drv(dev->bus, NULL, &data, __device_attach_driver);519514 dev_dbg(dev, "async probe completed\n");520515521516 pm_request_idle(dev);517517+518518+ if (dev->parent)519519+ pm_runtime_put(dev->parent);522520523521 device_unlock(dev);524522···555541 .want_async = false,556542 };557543544544+ if (dev->parent)545545+ pm_runtime_get_sync(dev->parent);546546+558547 ret = bus_for_each_drv(dev->bus, NULL, &data,559548 __device_attach_driver);560549 if (!ret && allow_async && data.have_async) {···574557 } else {575558 pm_request_idle(dev);576559 }560560+561561+ if (dev->parent)562562+ pm_runtime_put(dev->parent);577563 }578564out_unlock:579565 device_unlock(dev);
···8585 help8686 Enable support for the Intel(R) IOP Series RAID engines.87878888+config IDMA648989+ tristate "Intel integrated DMA 64-bit support"9090+ select DMA_ENGINE9191+ select DMA_VIRTUAL_CHANNELS9292+ help9393+ Enable DMA support for Intel Low Power Subsystem such as found on9494+ Intel Skylake PCH.9595+8896source "drivers/dma/dw/Kconfig"89979098config AT_HDMAC
···328328 thermal, charger and related power management functions329329 on these systems.330330331331+config MFD_INTEL_LPSS332332+ tristate333333+ select COMMON_CLK334334+ select MFD_CORE335335+336336+config MFD_INTEL_LPSS_ACPI337337+ tristate "Intel Low Power Subsystem support in ACPI mode"338338+ select MFD_INTEL_LPSS339339+ depends on X86 && ACPI340340+ help341341+ This driver supports Intel Low Power Subsystem (LPSS) devices such as342342+ I2C, SPI and HS-UART starting from Intel Sunrisepoint (Intel Skylake343343+ PCH) in ACPI mode.344344+345345+config MFD_INTEL_LPSS_PCI346346+ tristate "Intel Low Power Subsystem support in PCI mode"347347+ select MFD_INTEL_LPSS348348+ depends on X86 && PCI349349+ help350350+ This driver supports Intel Low Power Subsystem (LPSS) devices such as351351+ I2C, SPI and HS-UART starting from Intel Sunrisepoint (Intel Skylake352352+ PCH) in PCI mode.353353+331354config MFD_INTEL_MSIC332355 bool "Intel MSIC"333356 depends on INTEL_SCU_IPC
···324324}325325326326/**327327+ * klist_prev - Ante up prev node in list.328328+ * @i: Iterator structure.329329+ *330330+ * First grab list lock. Decrement the reference count of the previous331331+ * node, if there was one. Grab the prev node, increment its reference332332+ * count, drop the lock, and return that prev node.333333+ */334334+struct klist_node *klist_prev(struct klist_iter *i)335335+{336336+ void (*put)(struct klist_node *) = i->i_klist->put;337337+ struct klist_node *last = i->i_cur;338338+ struct klist_node *prev;339339+340340+ spin_lock(&i->i_klist->k_lock);341341+342342+ if (last) {343343+ prev = to_klist_node(last->n_node.prev);344344+ if (!klist_dec_and_del(last))345345+ put = NULL;346346+ } else347347+ prev = to_klist_node(i->i_klist->k_list.prev);348348+349349+ i->i_cur = NULL;350350+ while (prev != to_klist_node(&i->i_klist->k_list)) {351351+ if (likely(!knode_dead(prev))) {352352+ kref_get(&prev->n_ref);353353+ i->i_cur = prev;354354+ break;355355+ }356356+ prev = to_klist_node(prev->n_node.prev);357357+ }358358+359359+ spin_unlock(&i->i_klist->k_lock);360360+361361+ if (put && last)362362+ put(last);363363+ return i->i_cur;364364+}365365+EXPORT_SYMBOL_GPL(klist_prev);366366+367367+/**327368 * klist_next - Ante up next node in list.328369 * @i: Iterator structure.329370 *