Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ipmi/ipmi.c
Show All 30 Lines | |||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#include <sys/condvar.h> | #include <sys/condvar.h> | ||||
#include <sys/conf.h> | #include <sys/conf.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/poll.h> | #include <sys/poll.h> | ||||
#include <sys/reboot.h> | |||||
#include <sys/rman.h> | #include <sys/rman.h> | ||||
#include <sys/selinfo.h> | #include <sys/selinfo.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/watchdog.h> | #include <sys/watchdog.h> | ||||
#ifdef LOCAL_MODULE | #ifdef LOCAL_MODULE | ||||
#include <ipmi.h> | #include <ipmi.h> | ||||
#include <ipmivars.h> | #include <ipmivars.h> | ||||
▲ Show 20 Lines • Show All 638 Lines • ▼ Show 20 Lines | ipmi_wd_event(void *arg, unsigned int cmd, int *error) | ||||
} else if (atomic_readandclear_int(&sc->ipmi_watchdog_active) != 0) { | } else if (atomic_readandclear_int(&sc->ipmi_watchdog_active) != 0) { | ||||
e = ipmi_set_watchdog(sc, 0); | e = ipmi_set_watchdog(sc, 0); | ||||
if (e != 0 && cmd == 0) | if (e != 0 && cmd == 0) | ||||
*error = EOPNOTSUPP; | *error = EOPNOTSUPP; | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
ipmi_power_cycle(void *arg, int howto) | |||||
{ | |||||
struct ipmi_softc *sc = arg; | |||||
struct ipmi_request *req; | |||||
jtl: Where is ipmi_req defined? Or, is this supposed to be sc->ipmi_static_req?
Is there a reason… | |||||
Done Inline ActionsDoh! It was a last minute change to ipmi_static_req in the header... I wanted to make sure there was sufficient stack space, but I suppose that's a good assumption... imp: Doh! It was a last minute change to ipmi_static_req in the header...
I wanted to make sure… | |||||
/* | |||||
* Ignore everything except power cycling requests | |||||
*/ | |||||
if ((howto & RB_POWERCYCLE) == 0) | |||||
return; | |||||
printf("Power cycling using IPMI\n"); | |||||
/* | |||||
* Send a CHASSIS_CONTROL command to the CHASSIS device, subcommand 2 | |||||
* as described in IPMI v2.0 spec section 28.3. | |||||
*/ | |||||
IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_CHASSIS_REQUEST, 0), | |||||
IPMI_CHASSIS_CONTROL, 1, 0); | |||||
req->ir_request[0] = IPMI_CC_POWER_CYCLE; | |||||
ipmi_submit_driver_request(sc, req, MAX_TIMEOUT); | |||||
if (req->ir_error != 0 || req->ir_compcode != 0) { | |||||
printf("Power cycling via IPMI failed code %#x %#x\n", | |||||
req->ir_error, req->ir_compcode); | |||||
return; | |||||
} | |||||
/* | |||||
* BMCs are notoriously slow, give it up to 10s to effect the power | |||||
* down leg of the power cycle. If that fails, fallback to the next | |||||
* hanlder in the shutdown_final chain and/or the platform failsafe. | |||||
Not Done Inline Actionss/hanlder/handler/ dab: s/hanlder/handler/ | |||||
*/ | |||||
DELAY(10 * 1000 * 1000); | |||||
printf("Power cycling via IPMI timed out\n"); | |||||
} | |||||
static void | |||||
ipmi_startup(void *arg) | ipmi_startup(void *arg) | ||||
{ | { | ||||
struct ipmi_softc *sc = arg; | struct ipmi_softc *sc = arg; | ||||
struct ipmi_request *req; | struct ipmi_request *req; | ||||
device_t dev; | device_t dev; | ||||
int error, i; | int error, i; | ||||
config_intrhook_disestablish(&sc->ipmi_ich); | config_intrhook_disestablish(&sc->ipmi_ich); | ||||
Show All 36 Lines | ipmi_startup(void *arg) | ||||
} | } | ||||
device_printf(dev, "IPMI device rev. %d, firmware rev. %d.%d%d, " | device_printf(dev, "IPMI device rev. %d, firmware rev. %d.%d%d, " | ||||
"version %d.%d\n", | "version %d.%d\n", | ||||
req->ir_reply[1] & 0x0f, | req->ir_reply[1] & 0x0f, | ||||
req->ir_reply[2] & 0x7f, req->ir_reply[3] >> 4, req->ir_reply[3] & 0x0f, | req->ir_reply[2] & 0x7f, req->ir_reply[3] >> 4, req->ir_reply[3] & 0x0f, | ||||
req->ir_reply[4] & 0x0f, req->ir_reply[4] >> 4); | req->ir_reply[4] & 0x0f, req->ir_reply[4] >> 4); | ||||
sc->ipmi_dev_support = req->ir_reply[5]; | |||||
IPMI_INIT_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0), | IPMI_INIT_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0), | ||||
IPMI_CLEAR_FLAGS, 1, 0); | IPMI_CLEAR_FLAGS, 1, 0); | ||||
ipmi_submit_driver_request(sc, req, 0); | ipmi_submit_driver_request(sc, req, 0); | ||||
/* XXX: Magic numbers */ | /* XXX: Magic numbers */ | ||||
if (req->ir_compcode == 0xc0) { | if (req->ir_compcode == 0xc0) { | ||||
device_printf(dev, "Clear flags is busy\n"); | device_printf(dev, "Clear flags is busy\n"); | ||||
Show All 34 Lines | ipmi_startup(void *arg) | ||||
sc->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)); | UID_ROOT, GID_OPERATOR, 0660, "ipmi%d", device_get_unit(dev)); | ||||
if (sc->ipmi_cdev == NULL) { | if (sc->ipmi_cdev == NULL) { | ||||
device_printf(dev, "Failed to create cdev\n"); | device_printf(dev, "Failed to create cdev\n"); | ||||
return; | return; | ||||
} | } | ||||
sc->ipmi_cdev->si_drv1 = sc; | sc->ipmi_cdev->si_drv1 = sc; | ||||
/* | |||||
* Power cycle the system off using IPMI. We use last - 1 since we don't | |||||
Not Done Inline Actionss/system off/system/ (power cycle implies off/on, not just off) dab: s/system off/system/
(power cycle implies off/on, not just off) | |||||
* handle all the other kinds of reboots. We'll let others handle them. | |||||
* We only try to do this if the BMC supports the Chassis device. | |||||
*/ | |||||
if (sc->ipmi_dev_support & IPMI_ADS_CHASSIS) | |||||
sc->ipmi_power_cycle_tag = EVENTHANDLER_REGISTER(shutdown_final, | |||||
ipmi_power_cycle, sc, SHUTDOWN_PRI_LAST - 1); | |||||
} | } | ||||
int | int | ||||
ipmi_attach(device_t dev) | ipmi_attach(device_t dev) | ||||
{ | { | ||||
struct ipmi_softc *sc = device_get_softc(dev); | struct ipmi_softc *sc = device_get_softc(dev); | ||||
int error; | int error; | ||||
Show All 35 Lines | ipmi_detach(device_t dev) | ||||
if (sc->ipmi_cdev) | if (sc->ipmi_cdev) | ||||
destroy_dev(sc->ipmi_cdev); | destroy_dev(sc->ipmi_cdev); | ||||
/* Detach from watchdog handling and turn off watchdog. */ | /* Detach from watchdog handling and turn off watchdog. */ | ||||
if (sc->ipmi_watchdog_tag) { | if (sc->ipmi_watchdog_tag) { | ||||
EVENTHANDLER_DEREGISTER(watchdog_list, sc->ipmi_watchdog_tag); | EVENTHANDLER_DEREGISTER(watchdog_list, sc->ipmi_watchdog_tag); | ||||
ipmi_set_watchdog(sc, 0); | ipmi_set_watchdog(sc, 0); | ||||
} | } | ||||
/* Detach from watchdog handling and turn off watchdog. */ | |||||
Done Inline ActionsUpdate this comment. vangyzen: Update this comment. | |||||
if (sc->ipmi_power_cycle_tag) | |||||
EVENTHANDLER_DEREGISTER(shutdown_final, sc->ipmi_power_cycle_tag); | |||||
/* XXX: should use shutdown callout I think. */ | /* XXX: should use shutdown callout I think. */ | ||||
/* If the backend uses a kthread, shut it down. */ | /* If the backend uses a kthread, shut it down. */ | ||||
IPMI_LOCK(sc); | IPMI_LOCK(sc); | ||||
sc->ipmi_detaching = 1; | sc->ipmi_detaching = 1; | ||||
if (sc->ipmi_kthread) { | if (sc->ipmi_kthread) { | ||||
cv_broadcast(&sc->ipmi_request_added); | cv_broadcast(&sc->ipmi_request_added); | ||||
msleep(sc->ipmi_kthread, &sc->ipmi_requests_lock, 0, | msleep(sc->ipmi_kthread, &sc->ipmi_requests_lock, 0, | ||||
▲ Show 20 Lines • Show All 87 Lines • Show Last 20 Lines |
Where is ipmi_req defined? Or, is this supposed to be sc->ipmi_static_req?
Is there a reason not to use IPMI_ALLOC_DRIVER_REQUEST()?