diff options
author | jhb <jhb@FreeBSD.org> | 2008-08-28 02:13:53 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2008-08-28 02:13:53 +0000 |
commit | db890a1eb5b814a0367ca9de9f9a8f211f1231e7 (patch) | |
tree | 16917b153f668d155cffe7d32200f410a974d5d3 | |
parent | ba0db7a43b78a0da7a0fd53147fbd54a70b5c75f (diff) | |
download | FreeBSD-src-db890a1eb5b814a0367ca9de9f9a8f211f1231e7.zip FreeBSD-src-db890a1eb5b814a0367ca9de9f9a8f211f1231e7.tar.gz |
Remove hack attempt at using devfs cloning for per-file descriptor storage.
Use the much simpler cdevpriv for per-fd state and enable it. This allows
multiple opens of /dev/ipmi0 (e.g. using ipmitool while ipmievd is running
in the background).
MFC after: 1 week
-rw-r--r-- | sys/dev/ipmi/ipmi.c | 155 | ||||
-rw-r--r-- | sys/dev/ipmi/ipmivars.h | 16 |
2 files changed, 37 insertions, 134 deletions
diff --git a/sys/dev/ipmi/ipmi.c b/sys/dev/ipmi/ipmi.c index d42aedc..6d9c24d 100644 --- a/sys/dev/ipmi/ipmi.c +++ b/sys/dev/ipmi/ipmi.c @@ -58,12 +58,10 @@ static int ipmi_ipmb_send_message(device_t, u_char, u_char, u_char, static d_ioctl_t ipmi_ioctl; static d_poll_t ipmi_poll; static d_open_t ipmi_open; -static d_close_t ipmi_close; +static void ipmi_dtor(void *arg); int ipmi_attached = 0; -#define IPMI_MINOR 0 - static int on = 1; SYSCTL_NODE(_hw, OID_AUTO, ipmi, CTLFLAG_RD, 0, "IPMI driver parameters"); SYSCTL_INT(_hw_ipmi, OID_AUTO, on, CTLFLAG_RW, @@ -72,7 +70,6 @@ SYSCTL_INT(_hw_ipmi, OID_AUTO, on, CTLFLAG_RW, static struct cdevsw ipmi_cdevsw = { .d_version = D_VERSION, .d_open = ipmi_open, - .d_close = ipmi_close, .d_ioctl = ipmi_ioctl, .d_poll = ipmi_poll, .d_name = "ipmi", @@ -85,18 +82,26 @@ ipmi_open(struct cdev *cdev, int flags, int fmt, struct thread *td) { struct ipmi_device *dev; struct ipmi_softc *sc; + int error; if (!on) return (ENOENT); - dev = cdev->si_drv1; - sc = dev->ipmi_softc; - IPMI_LOCK(sc); - if (dev->ipmi_open) { - IPMI_UNLOCK(sc); - return (EBUSY); + /* Initialize the per file descriptor data. */ + dev = malloc(sizeof(struct ipmi_device), M_IPMI, M_WAITOK | M_ZERO); + error = devfs_set_cdevpriv(dev, ipmi_dtor); + if (error) { + free(dev, M_IPMI); + return (error); } - dev->ipmi_open = 1; + + sc = cdev->si_drv1; + TAILQ_INIT(&dev->ipmi_completed_requests); + dev->ipmi_address = IPMI_BMC_SLAVE_ADDR; + dev->ipmi_lun = IPMI_BMC_SMS_LUN; + dev->ipmi_softc = sc; + IPMI_LOCK(sc); + sc->ipmi_opened++; IPMI_UNLOCK(sc); return (0); @@ -109,9 +114,10 @@ ipmi_poll(struct cdev *cdev, int poll_events, struct thread *td) struct ipmi_softc *sc; int revents = 0; - dev = cdev->si_drv1; - sc = dev->ipmi_softc; + if (devfs_get_cdevpriv((void **)&dev)) + return (0); + sc = cdev->si_drv1; IPMI_LOCK(sc); if (poll_events & (POLLIN | POLLRDNORM)) { if (!TAILQ_EMPTY(&dev->ipmi_completed_requests)) @@ -142,17 +148,14 @@ ipmi_purge_completed_requests(struct ipmi_device *dev) } } -static int -ipmi_close(struct cdev *cdev, int flags, int fmt, struct thread *td) +static void +ipmi_dtor(void *arg) { struct ipmi_request *req, *nreq; struct ipmi_device *dev; struct ipmi_softc *sc; -#ifdef CLONING - int bit; -#endif - dev = cdev->si_drv1; + dev = arg; sc = dev->ipmi_softc; IPMI_LOCK(sc); @@ -182,24 +185,11 @@ ipmi_close(struct cdev *cdev, int flags, int fmt, struct thread *td) ipmi_purge_completed_requests(dev); } } - -#ifdef CLONING - /* Detach this sub-device from the main driver. */ - bit = minor(cdev) % 32; - sc->ipmi_cdev_mask &= ~(1 << bit); - TAILQ_REMOVE(&sc->ipmi_cdevs, dev, ipmi_link); + sc->ipmi_opened--; IPMI_UNLOCK(sc); /* Cleanup. */ - cdev->si_drv1 = NULL; free(dev, M_IPMI); - destroy_dev(cdev); -#else - dev->ipmi_open = 0; - IPMI_UNLOCK(sc); -#endif - - return (0); } #ifdef IPMB @@ -308,8 +298,11 @@ ipmi_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, #endif int error, len; - dev = cdev->si_drv1; - sc = dev->ipmi_softc; + error = devfs_get_cdevpriv((void **)&dev); + if (error) + return (error); + + sc = cdev->si_drv1; #ifdef IPMICTL_SEND_COMMAND_32 /* Convert 32-bit structures to native. */ @@ -659,58 +652,6 @@ ipmi_wd_event(void *arg, unsigned int cmd, int *error) } } -#ifdef CLONING -static void -ipmi_clone(void *arg, struct ucred *cred, char *name, int namelen, - struct cdev **cdev) -{ - struct ipmi_softc *sc = arg; - struct ipmi_device *dev; - int minor, unit; - - if (*cdev != NULL) - return; - - if (strcmp(name, device_get_nameunit(sc->ipmi_dev)) != 0) - return; - - dev = malloc(sizeof(struct ipmi_device), M_IPMI, M_WAITOK | M_ZERO); - - /* Reserve a sub-device. */ - IPMI_LOCK(sc); - minor = ffs(~(sc->ipmi_cdev_mask & 0xffff)); - if (minor == 0 || !sc->ipmi_cloning) { - IPMI_UNLOCK(sc); - free(dev, M_IPMI); - return; - } - minor--; - sc->ipmi_cdev_mask |= (1 << minor); - TAILQ_INSERT_TAIL(&sc->ipmi_cdevs, dev, ipmi_link); - IPMI_UNLOCK(sc); - - /* Initialize the device. */ - TAILQ_INIT(&dev->ipmi_completed_requests); - dev->ipmi_softc = sc; - dev->ipmi_address = IPMI_BMC_SLAVE_ADDR; - dev->ipmi_lun = IPMI_BMC_SMS_LUN; - unit = device_get_unit(sc->ipmi_dev); - dev->ipmi_cdev = make_dev_cred(&ipmi_cdevsw, unit * 32 + minor, cred, - UID_ROOT, GID_OPERATOR, 0660, "ipmi%d.%d", unit, minor); - if (dev->ipmi_cdev == NULL) { - IPMI_LOCK(sc); - sc->ipmi_cdev_mask &= ~(1 << minor); - TAILQ_REMOVE(&sc->ipmi_cdevs, dev, ipmi_link); - IPMI_UNLOCK(sc); - free(dev, M_IPMI); - return; - } - dev->ipmi_cdev->si_drv1 = dev; - *cdev = dev->ipmi_cdev; - dev_ref(*cdev); -} -#endif - static void ipmi_startup(void *arg) { @@ -726,9 +667,6 @@ ipmi_startup(void *arg) mtx_init(&sc->ipmi_lock, device_get_nameunit(dev), "ipmi", MTX_DEF); cv_init(&sc->ipmi_request_added, "ipmireq"); TAILQ_INIT(&sc->ipmi_pending_requests); -#ifdef CLONING - TAILQ_INIT(&sc->ipmi_cdevs); -#endif /* Initialize interface-dependent state. */ error = sc->ipmi_startup(sc); @@ -815,24 +753,13 @@ ipmi_startup(void *arg) } ipmi_free_request(req); -#ifdef CLONING - sc->ipmi_cloning = 1; - sc->ipmi_clone_tag = EVENTHANDLER_REGISTER(dev_clone, ipmi_clone, sc, - 1000); -#else - /* Initialize the device. */ - TAILQ_INIT(&sc->ipmi_idev.ipmi_completed_requests); - sc->ipmi_idev.ipmi_softc = sc; - sc->ipmi_idev.ipmi_address = IPMI_BMC_SLAVE_ADDR; - sc->ipmi_idev.ipmi_lun = IPMI_BMC_SMS_LUN; - sc->ipmi_idev.ipmi_cdev = make_dev(&ipmi_cdevsw, device_get_unit(dev), + sc->ipmi_cdev = make_dev(&ipmi_cdevsw, device_get_unit(dev), UID_ROOT, GID_OPERATOR, 0660, "ipmi%d", device_get_unit(dev)); - if (sc->ipmi_idev.ipmi_cdev == NULL) { + if (sc->ipmi_cdev == NULL) { device_printf(dev, "Failed to create cdev\n"); return; } - sc->ipmi_idev.ipmi_cdev->si_drv1 = &sc->ipmi_idev; -#endif + sc->ipmi_cdev->si_drv1 = sc; } int @@ -871,27 +798,13 @@ ipmi_detach(device_t dev) /* Fail if there are any open handles. */ IPMI_LOCK(sc); -#ifdef CLONING - if (!TAILQ_EMPTY(&sc->ipmi_cdevs)) { - IPMI_UNLOCK(sc); - return (EBUSY); - } - - /* Turn off cloning. */ - sc->ipmi_cloning = 0; - IPMI_UNLOCK(sc); - - if (sc->ipmi_clone_tag) - EVENTHANDLER_DEREGISTER(dev_clone, sc->ipmi_clone_tag); -#else - if (sc->ipmi_idev.ipmi_open) { + if (sc->ipmi_opened) { IPMI_UNLOCK(sc); return (EBUSY); } IPMI_UNLOCK(sc); - if (sc->ipmi_idev.ipmi_cdev) - destroy_dev(sc->ipmi_idev.ipmi_cdev); -#endif + if (sc->ipmi_cdev) + destroy_dev(sc->ipmi_cdev); /* Detach from watchdog handling and turn off watchdog. */ if (sc->ipmi_watchdog_tag) { diff --git a/sys/dev/ipmi/ipmivars.h b/sys/dev/ipmi/ipmivars.h index c56fb88..79d61f6 100644 --- a/sys/dev/ipmi/ipmivars.h +++ b/sys/dev/ipmi/ipmivars.h @@ -63,14 +63,12 @@ struct ipmi_request { struct ipmi_softc; -/* Per struct cdev data. */ +/* Per file descriptor data. */ struct ipmi_device { TAILQ_ENTRY(ipmi_device) ipmi_link; TAILQ_HEAD(,ipmi_request) ipmi_completed_requests; struct selinfo ipmi_select; struct ipmi_softc *ipmi_softc; - struct cdev *ipmi_cdev; - int ipmi_open; int ipmi_closing; int ipmi_requests; u_char ipmi_address; /* IPMB address. */ @@ -103,17 +101,9 @@ struct ipmi_softc { struct resource *ipmi_irq_res; void *ipmi_irq; int ipmi_detaching; -#ifdef CLONING - int ipmi_cloning; - u_int ipmi_cdev_mask; - TAILQ_HEAD(,ipmi_device) ipmi_cdevs; -#else - struct ipmi_device ipmi_idev; -#endif + int ipmi_opened; + struct cdev *ipmi_cdev; TAILQ_HEAD(,ipmi_request) ipmi_pending_requests; -#ifdef CLONING - eventhandler_tag ipmi_clone_tag; -#endif eventhandler_tag ipmi_watchdog_tag; struct intr_config_hook ipmi_ich; struct mtx ipmi_lock; |