summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/intel/io/ipmi/ipmi.c22
-rw-r--r--usr/src/uts/intel/io/ipmi/ipmi_main.c17
-rw-r--r--usr/src/uts/intel/io/ipmi/ipmivars.h5
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 {