ipmi: remove timeout from the ipmi_driver_request method
Driver requests are done with stack allocated request. The request is put on the tailq and then we msleep(9) until kernel process processes it. If we timeout from this sleep, the kernel process may still read the request from our stack, which may already be reused by some other code. Make this sleep unbound and rely on the kernel process that does all its I/O with timouts and will eventually wake us up. Reviewed by: jhb Differential Revision: https://reviews.freebsd.org/D47179
This commit is contained in:
+10
-11
@@ -360,7 +360,7 @@ ipmi_ioctl(struct cdev *cdev, u_long cmd, caddr_t data,
|
||||
kreq->ir_request[req->msg.data_len + 7] =
|
||||
ipmi_ipmb_checksum(&kreq->ir_request[4],
|
||||
req->msg.data_len + 3);
|
||||
error = ipmi_submit_driver_request(sc, kreq, MAX_TIMEOUT);
|
||||
error = ipmi_submit_driver_request(sc, kreq);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
@@ -565,11 +565,10 @@ ipmi_complete_request(struct ipmi_softc *sc, struct ipmi_request *req)
|
||||
|
||||
/* Perform an internal driver request. */
|
||||
int
|
||||
ipmi_submit_driver_request(struct ipmi_softc *sc, struct ipmi_request *req,
|
||||
int timo)
|
||||
ipmi_submit_driver_request(struct ipmi_softc *sc, struct ipmi_request *req)
|
||||
{
|
||||
|
||||
return (sc->ipmi_driver_request(sc, req, timo));
|
||||
return (sc->ipmi_driver_request(sc, req));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -636,7 +635,7 @@ ipmi_reset_watchdog(struct ipmi_softc *sc)
|
||||
|
||||
IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_RESET_WDOG, 0, 0);
|
||||
error = ipmi_submit_driver_request(sc, req, 0);
|
||||
error = ipmi_submit_driver_request(sc, req);
|
||||
if (error) {
|
||||
device_printf(sc->ipmi_dev, "Failed to reset watchdog\n");
|
||||
} else if (req->ir_compcode == 0x80) {
|
||||
@@ -677,7 +676,7 @@ ipmi_set_watchdog(struct ipmi_softc *sc, unsigned int sec)
|
||||
req->ir_request[4] = 0;
|
||||
req->ir_request[5] = 0;
|
||||
}
|
||||
error = ipmi_submit_driver_request(sc, req, 0);
|
||||
error = ipmi_submit_driver_request(sc, req);
|
||||
if (error) {
|
||||
device_printf(sc->ipmi_dev, "Failed to set watchdog\n");
|
||||
} else if (req->ir_compcode != 0) {
|
||||
@@ -812,7 +811,7 @@ ipmi_power_cycle(void *arg, int howto)
|
||||
IPMI_CHASSIS_CONTROL, 1, 0);
|
||||
req->ir_request[0] = IPMI_CC_POWER_CYCLE;
|
||||
|
||||
ipmi_submit_driver_request(sc, req, MAX_TIMEOUT);
|
||||
ipmi_submit_driver_request(sc, req);
|
||||
|
||||
if (req->ir_error != 0 || req->ir_compcode != 0) {
|
||||
device_printf(sc->ipmi_dev, "Power cycling via IPMI failed code %#x %#x\n",
|
||||
@@ -859,7 +858,7 @@ ipmi_startup(void *arg)
|
||||
IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_GET_DEVICE_ID, 0, 15);
|
||||
|
||||
error = ipmi_submit_driver_request(sc, req, MAX_TIMEOUT);
|
||||
error = ipmi_submit_driver_request(sc, req);
|
||||
if (error == EWOULDBLOCK) {
|
||||
device_printf(dev, "Timed out waiting for GET_DEVICE_ID\n");
|
||||
return;
|
||||
@@ -888,7 +887,7 @@ ipmi_startup(void *arg)
|
||||
IPMI_INIT_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_CLEAR_FLAGS, 1, 0);
|
||||
|
||||
ipmi_submit_driver_request(sc, req, 0);
|
||||
ipmi_submit_driver_request(sc, req);
|
||||
|
||||
/* XXX: Magic numbers */
|
||||
if (req->ir_compcode == 0xc0) {
|
||||
@@ -903,7 +902,7 @@ ipmi_startup(void *arg)
|
||||
IPMI_GET_CHANNEL_INFO, 1, 0);
|
||||
req->ir_request[0] = i;
|
||||
|
||||
error = ipmi_submit_driver_request(sc, req, 0);
|
||||
error = ipmi_submit_driver_request(sc, req);
|
||||
|
||||
if (error != 0 || req->ir_compcode != 0)
|
||||
break;
|
||||
@@ -918,7 +917,7 @@ ipmi_startup(void *arg)
|
||||
IPMI_INIT_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
|
||||
IPMI_GET_WDOG, 0, 0);
|
||||
|
||||
error = ipmi_submit_driver_request(sc, req, 0);
|
||||
error = ipmi_submit_driver_request(sc, req);
|
||||
|
||||
if (error == 0 && req->ir_compcode == 0x00) {
|
||||
device_printf(dev, "Attached watchdog\n");
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
#define BT_IM_BMC_HWRST (1L << 7)
|
||||
|
||||
static int bt_polled_request(struct ipmi_softc *, struct ipmi_request *);
|
||||
static int bt_driver_request(struct ipmi_softc *, struct ipmi_request *, int);
|
||||
static int bt_driver_request(struct ipmi_softc *, struct ipmi_request *);
|
||||
static int bt_wait(struct ipmi_softc *, uint8_t, uint8_t);
|
||||
static int bt_reset(struct ipmi_softc *);
|
||||
|
||||
@@ -247,7 +247,7 @@ bt_loop(void *arg)
|
||||
IPMI_LOCK(sc);
|
||||
while ((req = ipmi_dequeue_request(sc)) != NULL) {
|
||||
IPMI_UNLOCK(sc);
|
||||
(void)bt_driver_request(sc, req, 0);
|
||||
(void)bt_driver_request(sc, req);
|
||||
IPMI_LOCK(sc);
|
||||
sc->ipmi_bt_seq++;
|
||||
ipmi_complete_request(sc, req);
|
||||
@@ -265,7 +265,7 @@ bt_startup(struct ipmi_softc *sc)
|
||||
}
|
||||
|
||||
static int
|
||||
bt_driver_request(struct ipmi_softc *sc, struct ipmi_request *req, int timo __unused)
|
||||
bt_driver_request(struct ipmi_softc *sc, struct ipmi_request *req)
|
||||
{
|
||||
int i, ok;
|
||||
|
||||
|
||||
@@ -488,13 +488,13 @@ kcs_startup(struct ipmi_softc *sc)
|
||||
}
|
||||
|
||||
static int
|
||||
kcs_driver_request_queue(struct ipmi_softc *sc, struct ipmi_request *req, int timo)
|
||||
kcs_driver_request_queue(struct ipmi_softc *sc, struct ipmi_request *req)
|
||||
{
|
||||
int error;
|
||||
|
||||
IPMI_LOCK(sc);
|
||||
ipmi_polled_enqueue_request_highpri(sc, req);
|
||||
error = msleep(req, &sc->ipmi_requests_lock, 0, "ipmireq", timo);
|
||||
error = msleep(req, &sc->ipmi_requests_lock, 0, "ipmireq", 0);
|
||||
if (error == 0)
|
||||
error = req->ir_error;
|
||||
IPMI_UNLOCK(sc);
|
||||
@@ -517,13 +517,13 @@ kcs_driver_request_poll(struct ipmi_softc *sc, struct ipmi_request *req)
|
||||
}
|
||||
|
||||
static int
|
||||
kcs_driver_request(struct ipmi_softc *sc, struct ipmi_request *req, int timo)
|
||||
kcs_driver_request(struct ipmi_softc *sc, struct ipmi_request *req)
|
||||
{
|
||||
|
||||
if (KERNEL_PANICKED() || dumping)
|
||||
return (kcs_driver_request_poll(sc, req));
|
||||
else
|
||||
return (kcs_driver_request_queue(sc, req, timo));
|
||||
return (kcs_driver_request_queue(sc, req));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -142,8 +142,7 @@ opal_ipmi_discard_msgs(struct opal_ipmi_softc *sc)
|
||||
}
|
||||
|
||||
static int
|
||||
opal_ipmi_polled_request(struct opal_ipmi_softc *sc, struct ipmi_request *req,
|
||||
int timo)
|
||||
opal_ipmi_polled_request(struct opal_ipmi_softc *sc, struct ipmi_request *req)
|
||||
{
|
||||
uint64_t msg_len;
|
||||
int err;
|
||||
@@ -192,7 +191,7 @@ opal_ipmi_polled_request(struct opal_ipmi_softc *sc, struct ipmi_request *req,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((err = opal_ipmi_recv(sc, &msg_len, timo)) == 0) {
|
||||
if ((err = opal_ipmi_recv(sc, &msg_len, 0)) == 0) {
|
||||
/* Subtract one extra for the completion code. */
|
||||
req->ir_replylen = msg_len - sizeof(struct opal_ipmi_msg) - 1;
|
||||
req->ir_replylen = min(req->ir_replylen, req->ir_replybuflen);
|
||||
@@ -248,15 +247,14 @@ opal_ipmi_startup(struct ipmi_softc *sc)
|
||||
}
|
||||
|
||||
static int
|
||||
opal_ipmi_driver_request(struct ipmi_softc *isc, struct ipmi_request *req,
|
||||
int timo)
|
||||
opal_ipmi_driver_request(struct ipmi_softc *isc, struct ipmi_request *req)
|
||||
{
|
||||
struct opal_ipmi_softc *sc = (struct opal_ipmi_softc *)isc;
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
IPMI_LOCK(&sc->ipmi);
|
||||
err = opal_ipmi_polled_request(sc, req, timo);
|
||||
err = opal_ipmi_polled_request(sc, req);
|
||||
IPMI_UNLOCK(&sc->ipmi);
|
||||
if (err == 0)
|
||||
break;
|
||||
|
||||
@@ -388,7 +388,7 @@ smic_startup(struct ipmi_softc *sc)
|
||||
}
|
||||
|
||||
static int
|
||||
smic_driver_request(struct ipmi_softc *sc, struct ipmi_request *req, int timo)
|
||||
smic_driver_request(struct ipmi_softc *sc, struct ipmi_request *req)
|
||||
{
|
||||
int i, ok;
|
||||
|
||||
|
||||
@@ -359,15 +359,14 @@ ssif_startup(struct ipmi_softc *sc)
|
||||
}
|
||||
|
||||
static int
|
||||
ssif_driver_request(struct ipmi_softc *sc, struct ipmi_request *req, int timo)
|
||||
ssif_driver_request(struct ipmi_softc *sc, struct ipmi_request *req)
|
||||
{
|
||||
int error;
|
||||
|
||||
IPMI_LOCK(sc);
|
||||
error = ipmi_polled_enqueue_request(sc, req);
|
||||
if (error == 0)
|
||||
error = msleep(req, &sc->ipmi_requests_lock, 0, "ipmireq",
|
||||
timo);
|
||||
error = msleep(req, &sc->ipmi_requests_lock, 0, "ipmireq", 0);
|
||||
if (error == 0)
|
||||
error = req->ir_error;
|
||||
IPMI_UNLOCK(sc);
|
||||
|
||||
@@ -133,7 +133,7 @@ struct ipmi_softc {
|
||||
driver_intr_t *ipmi_intr;
|
||||
int (*ipmi_startup)(struct ipmi_softc *);
|
||||
int (*ipmi_enqueue_request)(struct ipmi_softc *, struct ipmi_request *);
|
||||
int (*ipmi_driver_request)(struct ipmi_softc *, struct ipmi_request *, int);
|
||||
int (*ipmi_driver_request)(struct ipmi_softc *, struct ipmi_request *);
|
||||
};
|
||||
|
||||
#define ipmi_ssif_smbus_address _iface.ssif.smbus_address
|
||||
@@ -247,8 +247,7 @@ struct ipmi_request *ipmi_dequeue_request(struct ipmi_softc *);
|
||||
void ipmi_free_request(struct ipmi_request *);
|
||||
int ipmi_polled_enqueue_request(struct ipmi_softc *, struct ipmi_request *);
|
||||
int ipmi_polled_enqueue_request_highpri(struct ipmi_softc *, struct ipmi_request *);
|
||||
int ipmi_submit_driver_request(struct ipmi_softc *, struct ipmi_request *,
|
||||
int);
|
||||
int ipmi_submit_driver_request(struct ipmi_softc *, struct ipmi_request *);
|
||||
|
||||
/* Identify BMC interface via SMBIOS. */
|
||||
int ipmi_smbios_identify(struct ipmi_get_info *);
|
||||
|
||||
Reference in New Issue
Block a user