^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * driver.c - device id matching, driver model, etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/pnp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "base.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static int compare_func(const char *ida, const char *idb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* we only need to compare the last 4 chars */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) for (i = 3; i < 7; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) if (ida[i] != 'X' &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) idb[i] != 'X' && toupper(ida[i]) != toupper(idb[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int compare_pnp_id(struct pnp_id *pos, const char *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (!pos || !id || (strlen(id) != 7))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (memcmp(id, "ANYDEVS", 7) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) while (pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (memcmp(pos->id, id, 3) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (compare_func(pos->id, id) == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) pos = pos->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static const struct pnp_device_id *match_device(struct pnp_driver *drv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct pnp_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) const struct pnp_device_id *drv_id = drv->id_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (!drv_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) while (*drv_id->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (compare_pnp_id(dev->id, drv_id->id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return drv_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) drv_id++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int pnp_device_attach(struct pnp_dev *pnp_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) mutex_lock(&pnp_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (pnp_dev->status != PNP_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) mutex_unlock(&pnp_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) pnp_dev->status = PNP_ATTACHED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) mutex_unlock(&pnp_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) void pnp_device_detach(struct pnp_dev *pnp_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) mutex_lock(&pnp_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (pnp_dev->status == PNP_ATTACHED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) pnp_dev->status = PNP_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) mutex_unlock(&pnp_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static int pnp_device_probe(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct pnp_driver *pnp_drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct pnp_dev *pnp_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) const struct pnp_device_id *dev_id = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) pnp_dev = to_pnp_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) pnp_drv = to_pnp_driver(dev->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) error = pnp_device_attach(pnp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (error < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (pnp_dev->active == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) error = pnp_activate_dev(pnp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (error < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) } else if ((pnp_drv->flags & PNP_DRIVER_RES_DISABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) == PNP_DRIVER_RES_DISABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) error = pnp_disable_dev(pnp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (error < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (pnp_drv->probe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) dev_id = match_device(pnp_drv, pnp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (dev_id != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) error = pnp_drv->probe(pnp_dev, dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (error >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) pnp_dev->driver = pnp_drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) pnp_device_detach(pnp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static int pnp_device_remove(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct pnp_dev *pnp_dev = to_pnp_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct pnp_driver *drv = pnp_dev->driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (drv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (drv->remove)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) drv->remove(pnp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) pnp_dev->driver = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (pnp_dev->active &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) (!drv || !(drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) pnp_disable_dev(pnp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) pnp_device_detach(pnp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static void pnp_device_shutdown(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct pnp_dev *pnp_dev = to_pnp_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct pnp_driver *drv = pnp_dev->driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (drv && drv->shutdown)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) drv->shutdown(pnp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static int pnp_bus_match(struct device *dev, struct device_driver *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct pnp_dev *pnp_dev = to_pnp_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct pnp_driver *pnp_drv = to_pnp_driver(drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (match_device(pnp_drv, pnp_dev) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static int __pnp_bus_suspend(struct device *dev, pm_message_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct pnp_dev *pnp_dev = to_pnp_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct pnp_driver *pnp_drv = pnp_dev->driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (!pnp_drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (pnp_drv->driver.pm && pnp_drv->driver.pm->suspend) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) error = pnp_drv->driver.pm->suspend(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) suspend_report_result(pnp_drv->driver.pm->suspend, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (pnp_drv->suspend) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) error = pnp_drv->suspend(pnp_dev, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (pnp_can_disable(pnp_dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) error = pnp_stop_dev(pnp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (pnp_can_suspend(pnp_dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) pnp_dev->protocol->suspend(pnp_dev, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static int pnp_bus_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return __pnp_bus_suspend(dev, PMSG_SUSPEND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static int pnp_bus_freeze(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return __pnp_bus_suspend(dev, PMSG_FREEZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static int pnp_bus_poweroff(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return __pnp_bus_suspend(dev, PMSG_HIBERNATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static int pnp_bus_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct pnp_dev *pnp_dev = to_pnp_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct pnp_driver *pnp_drv = pnp_dev->driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (!pnp_drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (pnp_dev->protocol->resume) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) error = pnp_dev->protocol->resume(pnp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (pnp_can_write(pnp_dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) error = pnp_start_dev(pnp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (pnp_drv->driver.pm && pnp_drv->driver.pm->resume) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) error = pnp_drv->driver.pm->resume(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (pnp_drv->resume) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) error = pnp_drv->resume(pnp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static const struct dev_pm_ops pnp_bus_dev_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* Suspend callbacks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) .suspend = pnp_bus_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) .resume = pnp_bus_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /* Hibernate callbacks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) .freeze = pnp_bus_freeze,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) .thaw = pnp_bus_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) .poweroff = pnp_bus_poweroff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) .restore = pnp_bus_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) struct bus_type pnp_bus_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) .name = "pnp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) .match = pnp_bus_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .probe = pnp_device_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) .remove = pnp_device_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .shutdown = pnp_device_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .pm = &pnp_bus_dev_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) .dev_groups = pnp_dev_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) int pnp_register_driver(struct pnp_driver *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) drv->driver.name = drv->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) drv->driver.bus = &pnp_bus_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return driver_register(&drv->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) void pnp_unregister_driver(struct pnp_driver *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) driver_unregister(&drv->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * pnp_add_id - adds an EISA id to the specified device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * @dev: pointer to the desired device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * @id: pointer to an EISA id string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct pnp_id *pnp_add_id(struct pnp_dev *dev, const char *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) struct pnp_id *dev_id, *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (!dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) dev_id->id[0] = id[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) dev_id->id[1] = id[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) dev_id->id[2] = id[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) dev_id->id[3] = tolower(id[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) dev_id->id[4] = tolower(id[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) dev_id->id[5] = tolower(id[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) dev_id->id[6] = tolower(id[6]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) dev_id->id[7] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) dev_id->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) ptr = dev->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) while (ptr && ptr->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) ptr = ptr->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) ptr->next = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) dev->id = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) EXPORT_SYMBOL(pnp_register_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) EXPORT_SYMBOL(pnp_unregister_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) EXPORT_SYMBOL(pnp_device_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) EXPORT_SYMBOL(pnp_device_detach);