Lines Matching +full:ipmi +full:- +full:ipmb

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
48 #include <ipmi.h>
51 #include <sys/ipmi.h>
52 #include <dev/ipmi/ipmivars.h>
92 static SYSCTL_NODE(_hw, OID_AUTO, ipmi, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
93 "IPMI driver parameters");
100 "IPMI watchdog timer actions (including pre-timeout interrupt)");
103 "IPMI watchdog countdown for shutdown (seconds)");
106 "IPMI watchdog countdown initialized during startup (seconds)");
109 "IPMI watchdog pre-timeout countdown (seconds)");
112 "IPMI power cycle on reboot delay time (seconds)");
119 .d_name = "ipmi",
122 static MALLOC_DEFINE(M_IPMI, "ipmi", "ipmi");
142 sc = cdev->si_drv1; in ipmi_open()
143 TAILQ_INIT(&dev->ipmi_completed_requests); in ipmi_open()
144 dev->ipmi_address = IPMI_BMC_SLAVE_ADDR; in ipmi_open()
145 dev->ipmi_lun = IPMI_BMC_SMS_LUN; in ipmi_open()
146 dev->ipmi_softc = sc; in ipmi_open()
148 sc->ipmi_opened++; in ipmi_open()
164 sc = cdev->si_drv1; in ipmi_poll()
167 if (!TAILQ_EMPTY(&dev->ipmi_completed_requests)) in ipmi_poll()
169 if (dev->ipmi_requests == 0) in ipmi_poll()
175 selrecord(td, &dev->ipmi_select); in ipmi_poll()
187 while (!TAILQ_EMPTY(&dev->ipmi_completed_requests)) { in ipmi_purge_completed_requests()
188 req = TAILQ_FIRST(&dev->ipmi_completed_requests); in ipmi_purge_completed_requests()
189 TAILQ_REMOVE(&dev->ipmi_completed_requests, req, ir_link); in ipmi_purge_completed_requests()
190 dev->ipmi_requests--; in ipmi_purge_completed_requests()
203 sc = dev->ipmi_softc; in ipmi_dtor()
206 if (dev->ipmi_requests) { in ipmi_dtor()
208 TAILQ_FOREACH_SAFE(req, &sc->ipmi_pending_requests_highpri, ir_link, in ipmi_dtor()
210 if (req->ir_owner == dev) { in ipmi_dtor()
211 TAILQ_REMOVE(&sc->ipmi_pending_requests_highpri, req, in ipmi_dtor()
213 dev->ipmi_requests--; in ipmi_dtor()
217 TAILQ_FOREACH_SAFE(req, &sc->ipmi_pending_requests, ir_link, in ipmi_dtor()
219 if (req->ir_owner == dev) { in ipmi_dtor()
220 TAILQ_REMOVE(&sc->ipmi_pending_requests, req, in ipmi_dtor()
222 dev->ipmi_requests--; in ipmi_dtor()
234 dev->ipmi_closing = 1; in ipmi_dtor()
235 while (dev->ipmi_requests > 0) { in ipmi_dtor()
236 msleep(&dev->ipmi_requests, &sc->ipmi_requests_lock, in ipmi_dtor()
241 sc->ipmi_opened--; in ipmi_dtor()
253 for (; len; len--) in ipmi_ipmb_checksum()
255 return (-sum); in ipmi_ipmb_checksum()
282 sc = cdev->si_drv1; in ipmi_ioctl()
285 /* Convert 32-bit structures to native. */ in ipmi_ioctl()
289 req->addr = PTRIN(req32->addr); in ipmi_ioctl()
290 req->addr_len = req32->addr_len; in ipmi_ioctl()
291 req->msgid = req32->msgid; in ipmi_ioctl()
292 req->msg.netfn = req32->msg.netfn; in ipmi_ioctl()
293 req->msg.cmd = req32->msg.cmd; in ipmi_ioctl()
294 req->msg.data_len = req32->msg.data_len; in ipmi_ioctl()
295 req->msg.data = PTRIN(req32->msg.data); in ipmi_ioctl()
300 recv->addr = PTRIN(recv32->addr); in ipmi_ioctl()
301 recv->addr_len = recv32->addr_len; in ipmi_ioctl()
302 recv->msg.data_len = recv32->msg.data_len; in ipmi_ioctl()
303 recv->msg.data = PTRIN(recv32->msg.data); in ipmi_ioctl()
313 error = copyin(req->addr, &addr, sizeof(addr)); in ipmi_ioctl()
321 kreq = ipmi_alloc_request(dev, req->msgid, in ipmi_ioctl()
322 IPMI_ADDR(req->msg.netfn, saddr->lun & 0x3), in ipmi_ioctl()
323 req->msg.cmd, req->msg.data_len, IPMI_MAX_RX); in ipmi_ioctl()
324 error = copyin(req->msg.data, kreq->ir_request, in ipmi_ioctl()
325 req->msg.data_len); in ipmi_ioctl()
331 dev->ipmi_requests++; in ipmi_ioctl()
332 error = sc->ipmi_enqueue_request(sc, kreq); in ipmi_ioctl()
339 /* Special processing for IPMB commands */ in ipmi_ioctl()
343 IPMI_SEND_MSG, req->msg.data_len + 8, IPMI_MAX_RX); in ipmi_ioctl()
345 kreq->ir_request[0] = iaddr->channel; in ipmi_ioctl()
346 kreq->ir_request[1] = iaddr->slave_addr; in ipmi_ioctl()
347 kreq->ir_request[2] = IPMI_ADDR(req->msg.netfn, iaddr->lun); in ipmi_ioctl()
348 kreq->ir_request[3] = in ipmi_ioctl()
349 ipmi_ipmb_checksum(&kreq->ir_request[1], 2); in ipmi_ioctl()
350 kreq->ir_request[4] = dev->ipmi_address; in ipmi_ioctl()
351 kreq->ir_request[5] = IPMI_ADDR(0, dev->ipmi_lun); in ipmi_ioctl()
352 kreq->ir_request[6] = req->msg.cmd; in ipmi_ioctl()
354 if (req->msg.data_len > 0) { in ipmi_ioctl()
355 error = copyin(req->msg.data, &kreq->ir_request[7], in ipmi_ioctl()
356 req->msg.data_len); in ipmi_ioctl()
360 kreq->ir_request[req->msg.data_len + 7] = in ipmi_ioctl()
361 ipmi_ipmb_checksum(&kreq->ir_request[4], in ipmi_ioctl()
362 req->msg.data_len + 3); in ipmi_ioctl()
367 kreq = ipmi_alloc_request(dev, req->msgid, in ipmi_ioctl()
370 kreq->ir_ipmb = true; in ipmi_ioctl()
371 kreq->ir_ipmb_addr = IPMI_ADDR(req->msg.netfn, 0); in ipmi_ioctl()
372 kreq->ir_ipmb_command = req->msg.cmd; in ipmi_ioctl()
374 dev->ipmi_requests++; in ipmi_ioctl()
375 error = sc->ipmi_enqueue_request(sc, kreq); in ipmi_ioctl()
386 error = copyin(recv->addr, &addr, sizeof(addr)); in ipmi_ioctl()
391 kreq = TAILQ_FIRST(&dev->ipmi_completed_requests); in ipmi_ioctl()
396 if (kreq->ir_error != 0) { in ipmi_ioctl()
397 error = kreq->ir_error; in ipmi_ioctl()
398 TAILQ_REMOVE(&dev->ipmi_completed_requests, kreq, in ipmi_ioctl()
400 dev->ipmi_requests--; in ipmi_ioctl()
406 recv->recv_type = IPMI_RESPONSE_RECV_TYPE; in ipmi_ioctl()
407 recv->msgid = kreq->ir_msgid; in ipmi_ioctl()
408 if (kreq->ir_ipmb) { in ipmi_ioctl()
410 recv->msg.netfn = in ipmi_ioctl()
411 IPMI_REPLY_ADDR(kreq->ir_ipmb_addr) >> 2; in ipmi_ioctl()
412 recv->msg.cmd = kreq->ir_ipmb_command; in ipmi_ioctl()
414 kreq->ir_compcode = kreq->ir_reply[6]; in ipmi_ioctl()
416 kreq->ir_reply += 7; in ipmi_ioctl()
417 len = kreq->ir_replylen - 7; in ipmi_ioctl()
420 recv->msg.netfn = IPMI_REPLY_ADDR(kreq->ir_addr) >> 2; in ipmi_ioctl()
421 recv->msg.cmd = kreq->ir_command; in ipmi_ioctl()
422 len = kreq->ir_replylen + 1; in ipmi_ioctl()
425 if (recv->msg.data_len < len && in ipmi_ioctl()
434 TAILQ_REMOVE(&dev->ipmi_completed_requests, kreq, ir_link); in ipmi_ioctl()
435 dev->ipmi_requests--; in ipmi_ioctl()
437 len = min(recv->msg.data_len, len); in ipmi_ioctl()
438 recv->msg.data_len = len; in ipmi_ioctl()
439 error = copyout(&addr, recv->addr,sizeof(addr)); in ipmi_ioctl()
441 error = copyout(&kreq->ir_compcode, recv->msg.data, 1); in ipmi_ioctl()
443 error = copyout(kreq->ir_reply, recv->msg.data + 1, in ipmi_ioctl()
444 len - 1); in ipmi_ioctl()
451 dev->ipmi_address = *(int*)data; in ipmi_ioctl()
456 *(int*)data = dev->ipmi_address; in ipmi_ioctl()
461 dev->ipmi_lun = *(int*)data & 0x3; in ipmi_ioctl()
466 *(int*)data = dev->ipmi_lun; in ipmi_ioctl()
471 device_printf(sc->ipmi_dev, in ipmi_ioctl()
479 device_printf(sc->ipmi_dev, "Unknown IOCTL %lX\n", cmd); in ipmi_ioctl()
484 /* Update changed fields in 32-bit structures. */ in ipmi_ioctl()
488 recv32->recv_type = recv->recv_type; in ipmi_ioctl()
489 recv32->msgid = recv->msgid; in ipmi_ioctl()
490 recv32->msg.netfn = recv->msg.netfn; in ipmi_ioctl()
491 recv32->msg.cmd = recv->msg.cmd; in ipmi_ioctl()
492 recv32->msg.data_len = recv->msg.data_len; in ipmi_ioctl()
508 req->ir_owner = dev; in ipmi_init_request()
509 req->ir_msgid = msgid; in ipmi_init_request()
510 req->ir_addr = addr; in ipmi_init_request()
511 req->ir_command = command; in ipmi_init_request()
513 req->ir_request = (char *)&req[1]; in ipmi_init_request()
514 req->ir_requestlen = requestlen; in ipmi_init_request()
517 req->ir_reply = (char *)&req[1] + requestlen; in ipmi_init_request()
518 req->ir_replybuflen = replylen; in ipmi_init_request()
555 if (req->ir_owner == NULL) in ipmi_complete_request()
558 dev = req->ir_owner; in ipmi_complete_request()
559 TAILQ_INSERT_TAIL(&dev->ipmi_completed_requests, req, ir_link); in ipmi_complete_request()
560 selwakeup(&dev->ipmi_select); in ipmi_complete_request()
561 if (dev->ipmi_closing) in ipmi_complete_request()
562 wakeup(&dev->ipmi_requests); in ipmi_complete_request()
571 return (sc->ipmi_driver_request(sc, req)); in ipmi_submit_driver_request()
587 while (!sc->ipmi_detaching && TAILQ_EMPTY(&sc->ipmi_pending_requests) && in ipmi_dequeue_request()
588 TAILQ_EMPTY(&sc->ipmi_pending_requests_highpri)) in ipmi_dequeue_request()
589 cv_wait(&sc->ipmi_request_added, &sc->ipmi_requests_lock); in ipmi_dequeue_request()
590 if (sc->ipmi_detaching) in ipmi_dequeue_request()
593 req = TAILQ_FIRST(&sc->ipmi_pending_requests_highpri); in ipmi_dequeue_request()
595 TAILQ_REMOVE(&sc->ipmi_pending_requests_highpri, req, ir_link); in ipmi_dequeue_request()
597 req = TAILQ_FIRST(&sc->ipmi_pending_requests); in ipmi_dequeue_request()
598 TAILQ_REMOVE(&sc->ipmi_pending_requests, req, ir_link); in ipmi_dequeue_request()
610 TAILQ_INSERT_TAIL(&sc->ipmi_pending_requests, req, ir_link); in ipmi_polled_enqueue_request()
611 cv_signal(&sc->ipmi_request_added); in ipmi_polled_enqueue_request()
621 TAILQ_INSERT_TAIL(&sc->ipmi_pending_requests_highpri, req, ir_link); in ipmi_polled_enqueue_request_highpri()
622 cv_signal(&sc->ipmi_request_added); in ipmi_polled_enqueue_request_highpri()
640 device_printf(sc->ipmi_dev, "Failed to reset watchdog\n"); in ipmi_reset_watchdog()
641 } else if (req->ir_compcode == 0x80) { in ipmi_reset_watchdog()
643 } else if (req->ir_compcode != 0) { in ipmi_reset_watchdog()
644 device_printf(sc->ipmi_dev, "Watchdog reset returned 0x%x\n", in ipmi_reset_watchdog()
645 req->ir_compcode); in ipmi_reset_watchdog()
663 req->ir_request[0] = IPMI_SET_WD_TIMER_DONT_STOP in ipmi_set_watchdog()
665 req->ir_request[1] = (wd_timer_actions & 0xff); in ipmi_set_watchdog()
666 req->ir_request[2] = min(0xff, in ipmi_set_watchdog()
668 req->ir_request[3] = 0; /* Timer use */ in ipmi_set_watchdog()
669 req->ir_request[4] = (sec * 10) & 0xff; in ipmi_set_watchdog()
670 req->ir_request[5] = (sec * 10) >> 8; in ipmi_set_watchdog()
672 req->ir_request[0] = IPMI_SET_WD_TIMER_SMS_OS; in ipmi_set_watchdog()
673 req->ir_request[1] = 0; in ipmi_set_watchdog()
674 req->ir_request[2] = 0; in ipmi_set_watchdog()
675 req->ir_request[3] = 0; /* Timer use */ in ipmi_set_watchdog()
676 req->ir_request[4] = 0; in ipmi_set_watchdog()
677 req->ir_request[5] = 0; in ipmi_set_watchdog()
681 device_printf(sc->ipmi_dev, "Failed to set watchdog\n"); in ipmi_set_watchdog()
682 } else if (req->ir_compcode != 0) { in ipmi_set_watchdog()
683 device_printf(sc->ipmi_dev, "Watchdog set returned 0x%x\n", in ipmi_set_watchdog()
684 req->ir_compcode); in ipmi_set_watchdog()
708 if (dumping && sc->ipmi_watchdog_active) in ipmi_wd_event()
718 if (timeout != sc->ipmi_watchdog_active || in ipmi_wd_event()
719 wd_timer_actions != sc->ipmi_watchdog_actions || in ipmi_wd_event()
720 wd_pretimeout_countdown != sc->ipmi_watchdog_pretimeout) { in ipmi_wd_event()
723 sc->ipmi_watchdog_active = timeout; in ipmi_wd_event()
724 sc->ipmi_watchdog_actions = wd_timer_actions; in ipmi_wd_event()
725 sc->ipmi_watchdog_pretimeout = wd_pretimeout_countdown; in ipmi_wd_event()
728 sc->ipmi_watchdog_active = 0; in ipmi_wd_event()
729 sc->ipmi_watchdog_actions = 0; in ipmi_wd_event()
730 sc->ipmi_watchdog_pretimeout = 0; in ipmi_wd_event()
733 if (sc->ipmi_watchdog_active != 0) { in ipmi_wd_event()
739 sc->ipmi_watchdog_active = 0; in ipmi_wd_event()
740 sc->ipmi_watchdog_actions = 0; in ipmi_wd_event()
741 sc->ipmi_watchdog_pretimeout = 0; in ipmi_wd_event()
744 } else if (atomic_readandclear_int(&sc->ipmi_watchdog_active) != 0) { in ipmi_wd_event()
745 sc->ipmi_watchdog_actions = 0; in ipmi_wd_event()
746 sc->ipmi_watchdog_pretimeout = 0; in ipmi_wd_event()
764 * Positive wd_shutdown_countdown value will re-arm watchdog; in ipmi_shutdown_event()
782 sc->ipmi_watchdog_active = 0; in ipmi_shutdown_event()
787 sc->ipmi_watchdog_active = wd_shutdown_countdown; in ipmi_shutdown_event()
804 device_printf(sc->ipmi_dev, "Power cycling using IPMI\n"); in ipmi_power_cycle()
808 * as described in IPMI v2.0 spec section 28.3. in ipmi_power_cycle()
812 req->ir_request[0] = IPMI_CC_POWER_CYCLE; in ipmi_power_cycle()
816 if (req->ir_error != 0 || req->ir_compcode != 0) { in ipmi_power_cycle()
817 device_printf(sc->ipmi_dev, "Power cycling via IPMI failed code %#x %#x\n", in ipmi_power_cycle()
818 req->ir_error, req->ir_compcode); in ipmi_power_cycle()
828 device_printf(sc->ipmi_dev, "Power cycling via IPMI timed out\n"); in ipmi_power_cycle()
839 config_intrhook_disestablish(&sc->ipmi_ich); in ipmi_startup()
840 dev = sc->ipmi_dev; in ipmi_startup()
842 /* Initialize interface-independent state. */ in ipmi_startup()
843 mtx_init(&sc->ipmi_requests_lock, "ipmi requests", NULL, MTX_DEF); in ipmi_startup()
844 mtx_init(&sc->ipmi_io_lock, "ipmi io", NULL, MTX_DEF); in ipmi_startup()
845 cv_init(&sc->ipmi_request_added, "ipmireq"); in ipmi_startup()
846 TAILQ_INIT(&sc->ipmi_pending_requests_highpri); in ipmi_startup()
847 TAILQ_INIT(&sc->ipmi_pending_requests); in ipmi_startup()
849 /* Initialize interface-dependent state. */ in ipmi_startup()
850 error = sc->ipmi_startup(sc); in ipmi_startup()
868 } else if (req->ir_compcode != 0) { in ipmi_startup()
871 req->ir_compcode); in ipmi_startup()
873 } else if (req->ir_replylen < 5) { in ipmi_startup()
875 req->ir_replylen); in ipmi_startup()
879 device_printf(dev, "IPMI device rev. %d, firmware rev. %d.%d%d, " in ipmi_startup()
881 req->ir_reply[1] & 0x0f, in ipmi_startup()
882 req->ir_reply[2] & 0x7f, req->ir_reply[3] >> 4, req->ir_reply[3] & 0x0f, in ipmi_startup()
883 req->ir_reply[4] & 0x0f, req->ir_reply[4] >> 4, req->ir_reply[5]); in ipmi_startup()
885 sc->ipmi_dev_support = req->ir_reply[5]; in ipmi_startup()
893 if (req->ir_compcode == 0xc0) { in ipmi_startup()
896 if (req->ir_compcode == 0xc1) { in ipmi_startup()
903 req->ir_request[0] = i; in ipmi_startup()
907 if (error != 0 || req->ir_compcode != 0) in ipmi_startup()
916 if (wd_init_enable && sc->ipmi_driver_requests_polled) { in ipmi_startup()
922 if (error == 0 && req->ir_compcode == 0x00) { in ipmi_startup()
925 sc->ipmi_watchdog_tag = EVENTHANDLER_REGISTER( in ipmi_startup()
927 sc->ipmi_shutdown_tag = EVENTHANDLER_REGISTER( in ipmi_startup()
933 sc->ipmi_cdev = make_dev(&ipmi_cdevsw, device_get_unit(dev), in ipmi_startup()
934 UID_ROOT, GID_OPERATOR, 0660, "ipmi%d", device_get_unit(dev)); in ipmi_startup()
935 if (sc->ipmi_cdev == NULL) { in ipmi_startup()
939 sc->ipmi_cdev->si_drv1 = sc; in ipmi_startup()
949 sc->ipmi_watchdog_active = wd_startup_countdown; in ipmi_startup()
950 sc->ipmi_watchdog_actions = wd_timer_actions; in ipmi_startup()
951 sc->ipmi_watchdog_pretimeout = wd_pretimeout_countdown; in ipmi_startup()
958 * Power cycle the system off using IPMI. We use last - 2 since we don't in ipmi_startup()
962 if (sc->ipmi_dev_support & IPMI_ADS_CHASSIS) { in ipmi_startup()
964 sc->ipmi_power_cycle_tag = EVENTHANDLER_REGISTER(shutdown_final, in ipmi_startup()
965 ipmi_power_cycle, sc, SHUTDOWN_PRI_LAST - 2); in ipmi_startup()
975 if (sc->ipmi_irq_res != NULL && sc->ipmi_intr != NULL) { in ipmi_attach()
976 error = bus_setup_intr(dev, sc->ipmi_irq_res, INTR_TYPE_MISC, in ipmi_attach()
977 NULL, sc->ipmi_intr, sc, &sc->ipmi_irq); in ipmi_attach()
984 bzero(&sc->ipmi_ich, sizeof(struct intr_config_hook)); in ipmi_attach()
985 sc->ipmi_ich.ich_func = ipmi_startup; in ipmi_attach()
986 sc->ipmi_ich.ich_arg = sc; in ipmi_attach()
987 if (config_intrhook_establish(&sc->ipmi_ich) != 0) { in ipmi_attach()
1005 if (sc->ipmi_opened) { in ipmi_detach()
1010 if (sc->ipmi_cdev) in ipmi_detach()
1011 destroy_dev(sc->ipmi_cdev); in ipmi_detach()
1014 if (sc->ipmi_shutdown_tag) in ipmi_detach()
1016 sc->ipmi_shutdown_tag); in ipmi_detach()
1017 if (sc->ipmi_watchdog_tag) { in ipmi_detach()
1018 EVENTHANDLER_DEREGISTER(watchdog_list, sc->ipmi_watchdog_tag); in ipmi_detach()
1023 if (sc->ipmi_power_cycle_tag) in ipmi_detach()
1024 EVENTHANDLER_DEREGISTER(shutdown_final, sc->ipmi_power_cycle_tag); in ipmi_detach()
1029 sc->ipmi_detaching = 1; in ipmi_detach()
1030 if (sc->ipmi_kthread) { in ipmi_detach()
1031 cv_broadcast(&sc->ipmi_request_added); in ipmi_detach()
1032 msleep(sc->ipmi_kthread, &sc->ipmi_requests_lock, 0, in ipmi_detach()
1036 if (sc->ipmi_irq) in ipmi_detach()
1037 bus_teardown_intr(dev, sc->ipmi_irq_res, sc->ipmi_irq); in ipmi_detach()
1040 mtx_destroy(&sc->ipmi_io_lock); in ipmi_detach()
1041 mtx_destroy(&sc->ipmi_requests_lock); in ipmi_detach()
1052 if (sc->ipmi_irq) in ipmi_release_resources()
1053 bus_teardown_intr(dev, sc->ipmi_irq_res, sc->ipmi_irq); in ipmi_release_resources()
1054 if (sc->ipmi_irq_res) in ipmi_release_resources()
1055 bus_release_resource(dev, SYS_RES_IRQ, sc->ipmi_irq_rid, in ipmi_release_resources()
1056 sc->ipmi_irq_res); in ipmi_release_resources()
1058 if (sc->ipmi_io_res[i]) in ipmi_release_resources()
1059 bus_release_resource(dev, sc->ipmi_io_type, in ipmi_release_resources()
1060 sc->ipmi_io_rid + i, sc->ipmi_io_res[i]); in ipmi_release_resources()
1071 if (devclass_get_devices(devclass_find("ipmi"), &devs, &count) != 0) in ipmi_unload()
1093 for (; len > 0; len--, data++) { in dump_buf()