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:
Gleb Smirnoff
2024-10-18 12:30:09 -07:00
parent 3b2cf9381e
commit 366d6a424e
7 changed files with 26 additions and 31 deletions
+10 -11
View File
@@ -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");
+3 -3
View File
@@ -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;
+4 -4
View File
@@ -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));
}
+4 -6
View File
@@ -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;
+1 -1
View File
@@ -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;
+2 -3
View File
@@ -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);
+2 -3
View File
@@ -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 *);