Deleted Added
full compact
subr_bus.c (278299) subr_bus.c (278320)
1/*-
2 * Copyright (c) 1997,1998,2003 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1997,1998,2003 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/kern/subr_bus.c 278299 2015-02-05 22:42:44Z jhb $");
28__FBSDID("$FreeBSD: head/sys/kern/subr_bus.c 278320 2015-02-06 16:09:01Z jhb $");
29
30#include "opt_bus.h"
31#include "opt_random.h"
32
33#include <sys/param.h>
34#include <sys/conf.h>
35#include <sys/filio.h>
36#include <sys/lock.h>
37#include <sys/kernel.h>
38#include <sys/kobj.h>
39#include <sys/limits.h>
40#include <sys/malloc.h>
41#include <sys/module.h>
42#include <sys/mutex.h>
43#include <sys/poll.h>
29
30#include "opt_bus.h"
31#include "opt_random.h"
32
33#include <sys/param.h>
34#include <sys/conf.h>
35#include <sys/filio.h>
36#include <sys/lock.h>
37#include <sys/kernel.h>
38#include <sys/kobj.h>
39#include <sys/limits.h>
40#include <sys/malloc.h>
41#include <sys/module.h>
42#include <sys/mutex.h>
43#include <sys/poll.h>
44#include <sys/priv.h>
44#include <sys/proc.h>
45#include <sys/condvar.h>
46#include <sys/queue.h>
47#include <machine/bus.h>
48#include <sys/random.h>
49#include <sys/rman.h>
50#include <sys/selinfo.h>
51#include <sys/signalvar.h>

--- 82 unchanged lines hidden (view full) ---

134
135 struct sysctl_ctx_list sysctl_ctx; /**< state for sysctl variables */
136 struct sysctl_oid *sysctl_tree; /**< state for sysctl variables */
137};
138
139static MALLOC_DEFINE(M_BUS, "bus", "Bus data structures");
140static MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc");
141
45#include <sys/proc.h>
46#include <sys/condvar.h>
47#include <sys/queue.h>
48#include <machine/bus.h>
49#include <sys/random.h>
50#include <sys/rman.h>
51#include <sys/selinfo.h>
52#include <sys/signalvar.h>

--- 82 unchanged lines hidden (view full) ---

135
136 struct sysctl_ctx_list sysctl_ctx; /**< state for sysctl variables */
137 struct sysctl_oid *sysctl_tree; /**< state for sysctl variables */
138};
139
140static MALLOC_DEFINE(M_BUS, "bus", "Bus data structures");
141static MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc");
142
143static void devctl2_init(void);
144
142#ifdef BUS_DEBUG
143
144static int bus_debug = 1;
145SYSCTL_INT(_debug, OID_AUTO, bus_debug, CTLFLAG_RWTUN, &bus_debug, 0,
146 "Bus debug level");
147
148#define PDEBUG(a) if (bus_debug) {printf("%s:%d: ", __func__, __LINE__), printf a; printf("\n");}
149#define DEVICENAME(d) ((d)? device_get_name(d): "no device")

--- 268 unchanged lines hidden (view full) ---

418devinit(void)
419{
420 devctl_dev = make_dev_credf(MAKEDEV_ETERNAL, &dev_cdevsw, 0, NULL,
421 UID_ROOT, GID_WHEEL, 0600, "devctl");
422 mtx_init(&devsoftc.mtx, "dev mtx", "devd", MTX_DEF);
423 cv_init(&devsoftc.cv, "dev cv");
424 TAILQ_INIT(&devsoftc.devq);
425 knlist_init_mtx(&devsoftc.sel.si_note, &devsoftc.mtx);
145#ifdef BUS_DEBUG
146
147static int bus_debug = 1;
148SYSCTL_INT(_debug, OID_AUTO, bus_debug, CTLFLAG_RWTUN, &bus_debug, 0,
149 "Bus debug level");
150
151#define PDEBUG(a) if (bus_debug) {printf("%s:%d: ", __func__, __LINE__), printf a; printf("\n");}
152#define DEVICENAME(d) ((d)? device_get_name(d): "no device")

--- 268 unchanged lines hidden (view full) ---

421devinit(void)
422{
423 devctl_dev = make_dev_credf(MAKEDEV_ETERNAL, &dev_cdevsw, 0, NULL,
424 UID_ROOT, GID_WHEEL, 0600, "devctl");
425 mtx_init(&devsoftc.mtx, "dev mtx", "devd", MTX_DEF);
426 cv_init(&devsoftc.cv, "dev cv");
427 TAILQ_INIT(&devsoftc.devq);
428 knlist_init_mtx(&devsoftc.sel.si_note, &devsoftc.mtx);
429 devctl2_init();
426}
427
428static int
429devopen(struct cdev *dev, int oflags, int devtype, struct thread *td)
430{
431
432 mtx_lock(&devsoftc.mtx);
433 if (devsoftc.inuse) {

--- 2200 unchanged lines hidden (view full) ---

2634 */
2635int
2636device_is_attached(device_t dev)
2637{
2638 return (dev->state >= DS_ATTACHED);
2639}
2640
2641/**
430}
431
432static int
433devopen(struct cdev *dev, int oflags, int devtype, struct thread *td)
434{
435
436 mtx_lock(&devsoftc.mtx);
437 if (devsoftc.inuse) {

--- 2200 unchanged lines hidden (view full) ---

2638 */
2639int
2640device_is_attached(device_t dev)
2641{
2642 return (dev->state >= DS_ATTACHED);
2643}
2644
2645/**
2646 * @brief Return non-zero if the device is currently suspended.
2647 */
2648int
2649device_is_suspended(device_t dev)
2650{
2651 return ((dev->flags & DF_SUSPENDED) != 0);
2652}
2653
2654/**
2642 * @brief Set the devclass of a device
2643 * @see devclass_add_device().
2644 */
2645int
2646device_set_devclass(device_t dev, const char *classname)
2647{
2648 devclass_t dc;
2649 int error;

--- 2367 unchanged lines hidden (view full) ---

5017
5018int
5019bus_free_resource(device_t dev, int type, struct resource *r)
5020{
5021 if (r == NULL)
5022 return (0);
5023 return (bus_release_resource(dev, type, rman_get_rid(r), r));
5024}
2655 * @brief Set the devclass of a device
2656 * @see devclass_add_device().
2657 */
2658int
2659device_set_devclass(device_t dev, const char *classname)
2660{
2661 devclass_t dc;
2662 int error;

--- 2367 unchanged lines hidden (view full) ---

5030
5031int
5032bus_free_resource(device_t dev, int type, struct resource *r)
5033{
5034 if (r == NULL)
5035 return (0);
5036 return (bus_release_resource(dev, type, rman_get_rid(r), r));
5037}
5038
5039/*
5040 * /dev/devctl2 implementation. The existing /dev/devctl device has
5041 * implicit semantics on open, so it could not be reused for this.
5042 * Another option would be to call this /dev/bus?
5043 */
5044static int
5045find_device(struct devreq *req, device_t *devp)
5046{
5047 device_t dev;
5048
5049 /*
5050 * First, ensure that the name is nul terminated.
5051 */
5052 if (memchr(req->dr_name, '\0', sizeof(req->dr_name)) == NULL)
5053 return (EINVAL);
5054
5055 /*
5056 * Second, try to find an attached device whose name matches
5057 * 'name'.
5058 */
5059 TAILQ_FOREACH(dev, &bus_data_devices, devlink) {
5060 if (dev->nameunit != NULL &&
5061 strcmp(dev->nameunit, req->dr_name) == 0) {
5062 *devp = dev;
5063 return (0);
5064 }
5065 }
5066
5067 /* Finally, give device enumerators a chance. */
5068 dev = NULL;
5069 EVENTHANDLER_INVOKE(dev_lookup, req->dr_name, &dev);
5070 if (dev == NULL)
5071 return (ENOENT);
5072 *devp = dev;
5073 return (0);
5074}
5075
5076static bool
5077driver_exists(struct device *bus, const char *driver)
5078{
5079 devclass_t dc;
5080
5081 for (dc = bus->devclass; dc != NULL; dc = dc->parent) {
5082 if (devclass_find_driver_internal(dc, driver) != NULL)
5083 return (true);
5084 }
5085 return (false);
5086}
5087
5088static int
5089devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
5090 struct thread *td)
5091{
5092 struct devreq *req;
5093 device_t dev;
5094 int error, old;
5095
5096 /* Locate the device to control. */
5097 mtx_lock(&Giant);
5098 req = (struct devreq *)data;
5099 switch (cmd) {
5100 case DEV_ATTACH:
5101 case DEV_DETACH:
5102 case DEV_ENABLE:
5103 case DEV_DISABLE:
5104 case DEV_SUSPEND:
5105 case DEV_RESUME:
5106 case DEV_SET_DRIVER:
5107 error = priv_check(td, PRIV_DRIVER);
5108 if (error == 0)
5109 error = find_device(req, &dev);
5110 break;
5111 default:
5112 error = ENOTTY;
5113 break;
5114 }
5115 if (error) {
5116 mtx_unlock(&Giant);
5117 return (error);
5118 }
5119
5120 /* Perform the requested operation. */
5121 switch (cmd) {
5122 case DEV_ATTACH:
5123 if (device_is_attached(dev) && (dev->flags & DF_REBID) == 0)
5124 error = EBUSY;
5125 else if (!device_is_enabled(dev))
5126 error = ENXIO;
5127 else
5128 error = device_probe_and_attach(dev);
5129 break;
5130 case DEV_DETACH:
5131 if (!device_is_attached(dev)) {
5132 error = ENXIO;
5133 break;
5134 }
5135 if (!(req->dr_flags & DEVF_FORCE_DETACH)) {
5136 error = device_quiesce(dev);
5137 if (error)
5138 break;
5139 }
5140 error = device_detach(dev);
5141 break;
5142 case DEV_ENABLE:
5143 if (device_is_enabled(dev)) {
5144 error = EBUSY;
5145 break;
5146 }
5147
5148 /*
5149 * If the device has been probed but not attached (e.g.
5150 * when it has been disabled by a loader hint), just
5151 * attach the device rather than doing a full probe.
5152 */
5153 device_enable(dev);
5154 if (device_is_alive(dev)) {
5155 /*
5156 * If the device was disabled via a hint, clear
5157 * the hint.
5158 */
5159 if (resource_disabled(dev->driver->name, dev->unit))
5160 resource_unset_value(dev->driver->name,
5161 dev->unit, "disabled");
5162 error = device_attach(dev);
5163 } else
5164 error = device_probe_and_attach(dev);
5165 break;
5166 case DEV_DISABLE:
5167 if (!device_is_enabled(dev)) {
5168 error = ENXIO;
5169 break;
5170 }
5171
5172 if (!(req->dr_flags & DEVF_FORCE_DETACH)) {
5173 error = device_quiesce(dev);
5174 if (error)
5175 break;
5176 }
5177
5178 /*
5179 * Force DF_FIXEDCLASS on around detach to preserve
5180 * the existing name.
5181 */
5182 old = dev->flags;
5183 dev->flags |= DF_FIXEDCLASS;
5184 error = device_detach(dev);
5185 if (!(old & DF_FIXEDCLASS))
5186 dev->flags &= ~DF_FIXEDCLASS;
5187 if (error == 0)
5188 device_disable(dev);
5189 break;
5190 case DEV_SUSPEND:
5191 if (device_is_suspended(dev)) {
5192 error = EBUSY;
5193 break;
5194 }
5195 if (device_get_parent(dev) == NULL) {
5196 error = EINVAL;
5197 break;
5198 }
5199 error = BUS_SUSPEND_CHILD(device_get_parent(dev), dev);
5200 break;
5201 case DEV_RESUME:
5202 if (!device_is_suspended(dev)) {
5203 error = EINVAL;
5204 break;
5205 }
5206 if (device_get_parent(dev) == NULL) {
5207 error = EINVAL;
5208 break;
5209 }
5210 error = BUS_RESUME_CHILD(device_get_parent(dev), dev);
5211 break;
5212 case DEV_SET_DRIVER: {
5213 devclass_t dc;
5214 char driver[128];
5215
5216 error = copyinstr(req->dr_data, driver, sizeof(driver), NULL);
5217 if (error)
5218 break;
5219 if (driver[0] == '\0') {
5220 error = EINVAL;
5221 break;
5222 }
5223 if (dev->devclass != NULL &&
5224 strcmp(driver, dev->devclass->name) == 0)
5225 /* XXX: Could possibly force DF_FIXEDCLASS on? */
5226 break;
5227
5228 /*
5229 * Scan drivers for this device's bus looking for at
5230 * least one matching driver.
5231 */
5232 if (dev->parent == NULL) {
5233 error = EINVAL;
5234 break;
5235 }
5236 if (!driver_exists(dev->parent, driver)) {
5237 error = ENOENT;
5238 break;
5239 }
5240 dc = devclass_create(driver);
5241 if (dc == NULL) {
5242 error = ENOMEM;
5243 break;
5244 }
5245
5246 /* Detach device if necessary. */
5247 if (device_is_attached(dev)) {
5248 if (req->dr_flags & DEVF_SET_DRIVER_DETACH)
5249 error = device_detach(dev);
5250 else
5251 error = EBUSY;
5252 if (error)
5253 break;
5254 }
5255
5256 /* Clear any previously-fixed device class and unit. */
5257 if (dev->flags & DF_FIXEDCLASS)
5258 devclass_delete_device(dev->devclass, dev);
5259 dev->flags |= DF_WILDCARD;
5260 dev->unit = -1;
5261
5262 /* Force the new device class. */
5263 error = devclass_add_device(dc, dev);
5264 if (error)
5265 break;
5266 dev->flags |= DF_FIXEDCLASS;
5267 error = device_probe_and_attach(dev);
5268 break;
5269 }
5270 }
5271 mtx_unlock(&Giant);
5272 return (error);
5273}
5274
5275static struct cdevsw devctl2_cdevsw = {
5276 .d_version = D_VERSION,
5277 .d_ioctl = devctl2_ioctl,
5278 .d_name = "devctl2",
5279};
5280
5281static void
5282devctl2_init(void)
5283{
5284
5285 make_dev_credf(MAKEDEV_ETERNAL, &devctl2_cdevsw, 0, NULL,
5286 UID_ROOT, GID_WHEEL, 0600, "devctl2");
5287}