diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/intel/io/ipmi/ipmi.c | 22 | ||||
-rw-r--r-- | usr/src/uts/intel/io/ipmi/ipmi_main.c | 17 | ||||
-rw-r--r-- | usr/src/uts/intel/io/ipmi/ipmivars.h | 5 |
3 files changed, 27 insertions, 17 deletions
diff --git a/usr/src/uts/intel/io/ipmi/ipmi.c b/usr/src/uts/intel/io/ipmi/ipmi.c index 8087d55db8..7fb5b757f6 100644 --- a/usr/src/uts/intel/io/ipmi/ipmi.c +++ b/usr/src/uts/intel/io/ipmi/ipmi.c @@ -103,22 +103,28 @@ ipmi_complete_request(struct ipmi_softc *sc, struct ipmi_request *req) IPMI_LOCK_ASSERT(sc); - /* - * Anonymous requests (from inside the driver) always have a - * waiter that we awaken. - */ if (req->ir_status == IRS_CANCELED) { ASSERT(req->ir_owner == NULL); ipmi_free_request(req); return; } + req->ir_status = IRS_COMPLETED; - cv_signal(&req->ir_cv); - if (req->ir_owner != NULL) { + /* + * Anonymous requests (from inside the driver) always have a + * waiter that we awaken. + */ + if (req->ir_owner == NULL) { + cv_signal(&req->ir_cv); + } else { dev = req->ir_owner; TAILQ_INSERT_TAIL(&dev->ipmi_completed_requests, req, ir_link); pollwakeup(dev->ipmi_pollhead, POLLIN | POLLRDNORM); + + dev->ipmi_status &= ~IPMI_BUSY; + if (dev->ipmi_status & IPMI_CLOSING) + cv_signal(&dev->ipmi_cv); } } @@ -193,6 +199,10 @@ ipmi_dequeue_request(struct ipmi_softc *sc) req = TAILQ_FIRST(&sc->ipmi_pending_requests); TAILQ_REMOVE(&sc->ipmi_pending_requests, req, ir_link); req->ir_status = IRS_PROCESSED; + + if (req->ir_owner != NULL) + req->ir_owner->ipmi_status |= IPMI_BUSY; + return (req); } diff --git a/usr/src/uts/intel/io/ipmi/ipmi_main.c b/usr/src/uts/intel/io/ipmi/ipmi_main.c index 4f4c53d7c9..b77434a0a5 100644 --- a/usr/src/uts/intel/io/ipmi/ipmi_main.c +++ b/usr/src/uts/intel/io/ipmi/ipmi_main.c @@ -170,6 +170,7 @@ ipmi_open(dev_t *devp, int flag, int otyp, cred_t *cred) dev->ipmi_lun = IPMI_BMC_SMS_LUN; *devp = makedevice(getmajor(*devp), minor); dev->ipmi_dev = *devp; + cv_init(&dev->ipmi_cv, NULL, CV_DEFAULT, NULL); list_insert_head(&dev_list, dev); @@ -198,6 +199,10 @@ ipmi_close(dev_t dev, int flag, int otyp, cred_t *cred) } req = next; } + + dp->ipmi_status |= IPMI_CLOSING; + while (dp->ipmi_status & IPMI_BUSY) + cv_wait(&dp->ipmi_cv, &sc->ipmi_lock); IPMI_UNLOCK(sc); /* remove any requests in queue of stuff completed */ @@ -208,6 +213,7 @@ ipmi_close(dev_t dev, int flag, int otyp, cred_t *cred) list_remove(&dev_list, dp); id_free(minor_ids, getminor(dev)); + cv_destroy(&dp->ipmi_cv); kmem_free(dp->ipmi_pollhead, sizeof (pollhead_t)); kmem_free(dp, sizeof (ipmi_device_t)); @@ -287,17 +293,6 @@ ipmi_ioctl(dev_t dv, int cmd, intptr_t data, int flags, cred_t *cr, int *rvalp) switch (cmd) { case IPMICTL_SEND_COMMAND: - IPMI_LOCK(sc); - /* clear out old stuff in queue of stuff done */ - while ((kreq = TAILQ_FIRST(&dev->ipmi_completed_requests)) - != NULL) { - TAILQ_REMOVE(&dev->ipmi_completed_requests, kreq, - ir_link); - dev->ipmi_requests--; - ipmi_free_request(kreq); - } - IPMI_UNLOCK(sc); - /* Check that we didn't get a ridiculous length */ if (req.msg.data_len > IPMI_MAX_RX) return (EINVAL); diff --git a/usr/src/uts/intel/io/ipmi/ipmivars.h b/usr/src/uts/intel/io/ipmi/ipmivars.h index 172ec4e489..7fd819cd3d 100644 --- a/usr/src/uts/intel/io/ipmi/ipmivars.h +++ b/usr/src/uts/intel/io/ipmi/ipmivars.h @@ -78,6 +78,9 @@ struct ipmi_request { #define SMIC_CTL_STS 1 #define SMIC_FLAGS 2 +#define IPMI_BUSY 0x1 +#define IPMI_CLOSING 0x2 + /* Per file descriptor data. */ typedef struct ipmi_device { TAILQ_HEAD(, ipmi_request) ipmi_completed_requests; @@ -87,6 +90,8 @@ typedef struct ipmi_device { uchar_t ipmi_lun; dev_t ipmi_dev; list_node_t ipmi_node; /* list link for open devs */ + int ipmi_status; + kcondvar_t ipmi_cv; } ipmi_device_t; struct ipmi_softc { |