Deleted Added
full compact
ipmi.c (167950) ipmi.c (182322)
1/*-
2 * Copyright (c) 2006 IronPort Systems Inc. <ambrisko@ironport.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2006 IronPort Systems Inc. <ambrisko@ironport.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/dev/ipmi/ipmi.c 167950 2007-03-27 21:03:37Z n_hibma $");
28__FBSDID("$FreeBSD: head/sys/dev/ipmi/ipmi.c 182322 2008-08-28 02:13:53Z jhb $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/bus.h>
33#include <sys/condvar.h>
34#include <sys/conf.h>
35#include <sys/kernel.h>
36#include <sys/malloc.h>

--- 16 unchanged lines hidden (view full) ---

53static int ipmi_ipmb_checksum(u_char, int);
54static int ipmi_ipmb_send_message(device_t, u_char, u_char, u_char,
55 u_char, u_char, int)
56#endif
57
58static d_ioctl_t ipmi_ioctl;
59static d_poll_t ipmi_poll;
60static d_open_t ipmi_open;
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/bus.h>
33#include <sys/condvar.h>
34#include <sys/conf.h>
35#include <sys/kernel.h>
36#include <sys/malloc.h>

--- 16 unchanged lines hidden (view full) ---

53static int ipmi_ipmb_checksum(u_char, int);
54static int ipmi_ipmb_send_message(device_t, u_char, u_char, u_char,
55 u_char, u_char, int)
56#endif
57
58static d_ioctl_t ipmi_ioctl;
59static d_poll_t ipmi_poll;
60static d_open_t ipmi_open;
61static d_close_t ipmi_close;
61static void ipmi_dtor(void *arg);
62
63int ipmi_attached = 0;
64
62
63int ipmi_attached = 0;
64
65#define IPMI_MINOR 0
66
67static int on = 1;
68SYSCTL_NODE(_hw, OID_AUTO, ipmi, CTLFLAG_RD, 0, "IPMI driver parameters");
69SYSCTL_INT(_hw_ipmi, OID_AUTO, on, CTLFLAG_RW,
70 &on, 0, "");
71
72static struct cdevsw ipmi_cdevsw = {
73 .d_version = D_VERSION,
74 .d_open = ipmi_open,
65static int on = 1;
66SYSCTL_NODE(_hw, OID_AUTO, ipmi, CTLFLAG_RD, 0, "IPMI driver parameters");
67SYSCTL_INT(_hw_ipmi, OID_AUTO, on, CTLFLAG_RW,
68 &on, 0, "");
69
70static struct cdevsw ipmi_cdevsw = {
71 .d_version = D_VERSION,
72 .d_open = ipmi_open,
75 .d_close = ipmi_close,
76 .d_ioctl = ipmi_ioctl,
77 .d_poll = ipmi_poll,
78 .d_name = "ipmi",
79};
80
81MALLOC_DEFINE(M_IPMI, "ipmi", "ipmi");
82
83static int
84ipmi_open(struct cdev *cdev, int flags, int fmt, struct thread *td)
85{
86 struct ipmi_device *dev;
87 struct ipmi_softc *sc;
73 .d_ioctl = ipmi_ioctl,
74 .d_poll = ipmi_poll,
75 .d_name = "ipmi",
76};
77
78MALLOC_DEFINE(M_IPMI, "ipmi", "ipmi");
79
80static int
81ipmi_open(struct cdev *cdev, int flags, int fmt, struct thread *td)
82{
83 struct ipmi_device *dev;
84 struct ipmi_softc *sc;
85 int error;
88
89 if (!on)
90 return (ENOENT);
91
86
87 if (!on)
88 return (ENOENT);
89
92 dev = cdev->si_drv1;
93 sc = dev->ipmi_softc;
94 IPMI_LOCK(sc);
95 if (dev->ipmi_open) {
96 IPMI_UNLOCK(sc);
97 return (EBUSY);
90 /* Initialize the per file descriptor data. */
91 dev = malloc(sizeof(struct ipmi_device), M_IPMI, M_WAITOK | M_ZERO);
92 error = devfs_set_cdevpriv(dev, ipmi_dtor);
93 if (error) {
94 free(dev, M_IPMI);
95 return (error);
98 }
96 }
99 dev->ipmi_open = 1;
97
98 sc = cdev->si_drv1;
99 TAILQ_INIT(&dev->ipmi_completed_requests);
100 dev->ipmi_address = IPMI_BMC_SLAVE_ADDR;
101 dev->ipmi_lun = IPMI_BMC_SMS_LUN;
102 dev->ipmi_softc = sc;
103 IPMI_LOCK(sc);
104 sc->ipmi_opened++;
100 IPMI_UNLOCK(sc);
101
102 return (0);
103}
104
105static int
106ipmi_poll(struct cdev *cdev, int poll_events, struct thread *td)
107{
108 struct ipmi_device *dev;
109 struct ipmi_softc *sc;
110 int revents = 0;
111
105 IPMI_UNLOCK(sc);
106
107 return (0);
108}
109
110static int
111ipmi_poll(struct cdev *cdev, int poll_events, struct thread *td)
112{
113 struct ipmi_device *dev;
114 struct ipmi_softc *sc;
115 int revents = 0;
116
112 dev = cdev->si_drv1;
113 sc = dev->ipmi_softc;
117 if (devfs_get_cdevpriv((void **)&dev))
118 return (0);
114
119
120 sc = cdev->si_drv1;
115 IPMI_LOCK(sc);
116 if (poll_events & (POLLIN | POLLRDNORM)) {
117 if (!TAILQ_EMPTY(&dev->ipmi_completed_requests))
118 revents |= poll_events & (POLLIN | POLLRDNORM);
119 if (dev->ipmi_requests == 0)
120 revents |= POLLERR;
121 }
122

--- 14 unchanged lines hidden (view full) ---

137 while (!TAILQ_EMPTY(&dev->ipmi_completed_requests)) {
138 req = TAILQ_FIRST(&dev->ipmi_completed_requests);
139 TAILQ_REMOVE(&dev->ipmi_completed_requests, req, ir_link);
140 dev->ipmi_requests--;
141 ipmi_free_request(req);
142 }
143}
144
121 IPMI_LOCK(sc);
122 if (poll_events & (POLLIN | POLLRDNORM)) {
123 if (!TAILQ_EMPTY(&dev->ipmi_completed_requests))
124 revents |= poll_events & (POLLIN | POLLRDNORM);
125 if (dev->ipmi_requests == 0)
126 revents |= POLLERR;
127 }
128

--- 14 unchanged lines hidden (view full) ---

143 while (!TAILQ_EMPTY(&dev->ipmi_completed_requests)) {
144 req = TAILQ_FIRST(&dev->ipmi_completed_requests);
145 TAILQ_REMOVE(&dev->ipmi_completed_requests, req, ir_link);
146 dev->ipmi_requests--;
147 ipmi_free_request(req);
148 }
149}
150
145static int
146ipmi_close(struct cdev *cdev, int flags, int fmt, struct thread *td)
151static void
152ipmi_dtor(void *arg)
147{
148 struct ipmi_request *req, *nreq;
149 struct ipmi_device *dev;
150 struct ipmi_softc *sc;
153{
154 struct ipmi_request *req, *nreq;
155 struct ipmi_device *dev;
156 struct ipmi_softc *sc;
151#ifdef CLONING
152 int bit;
153#endif
154
157
155 dev = cdev->si_drv1;
158 dev = arg;
156 sc = dev->ipmi_softc;
157
158 IPMI_LOCK(sc);
159 if (dev->ipmi_requests) {
160 /* Throw away any pending requests for this device. */
161 TAILQ_FOREACH_SAFE(req, &sc->ipmi_pending_requests, ir_link,
162 nreq) {
163 if (req->ir_owner == dev) {

--- 13 unchanged lines hidden (view full) ---

177 */
178 dev->ipmi_closing = 1;
179 while (dev->ipmi_requests > 0) {
180 msleep(&dev->ipmi_requests, &sc->ipmi_lock, PWAIT,
181 "ipmidrain", 0);
182 ipmi_purge_completed_requests(dev);
183 }
184 }
159 sc = dev->ipmi_softc;
160
161 IPMI_LOCK(sc);
162 if (dev->ipmi_requests) {
163 /* Throw away any pending requests for this device. */
164 TAILQ_FOREACH_SAFE(req, &sc->ipmi_pending_requests, ir_link,
165 nreq) {
166 if (req->ir_owner == dev) {

--- 13 unchanged lines hidden (view full) ---

180 */
181 dev->ipmi_closing = 1;
182 while (dev->ipmi_requests > 0) {
183 msleep(&dev->ipmi_requests, &sc->ipmi_lock, PWAIT,
184 "ipmidrain", 0);
185 ipmi_purge_completed_requests(dev);
186 }
187 }
185
186#ifdef CLONING
187 /* Detach this sub-device from the main driver. */
188 bit = minor(cdev) % 32;
189 sc->ipmi_cdev_mask &= ~(1 << bit);
190 TAILQ_REMOVE(&sc->ipmi_cdevs, dev, ipmi_link);
188 sc->ipmi_opened--;
191 IPMI_UNLOCK(sc);
192
193 /* Cleanup. */
189 IPMI_UNLOCK(sc);
190
191 /* Cleanup. */
194 cdev->si_drv1 = NULL;
195 free(dev, M_IPMI);
192 free(dev, M_IPMI);
196 destroy_dev(cdev);
197#else
198 dev->ipmi_open = 0;
199 IPMI_UNLOCK(sc);
200#endif
201
202 return (0);
203}
204
205#ifdef IPMB
206static int
207ipmi_ipmb_checksum(u_char *data, int len)
208{
209 u_char sum = 0;
210

--- 92 unchanged lines hidden (view full) ---

303 struct ipmi_recv32 *recv32 = (struct ipmi_recv32 *)data;
304 union {
305 struct ipmi_req req;
306 struct ipmi_recv recv;
307 } thunk32;
308#endif
309 int error, len;
310
193}
194
195#ifdef IPMB
196static int
197ipmi_ipmb_checksum(u_char *data, int len)
198{
199 u_char sum = 0;
200

--- 92 unchanged lines hidden (view full) ---

293 struct ipmi_recv32 *recv32 = (struct ipmi_recv32 *)data;
294 union {
295 struct ipmi_req req;
296 struct ipmi_recv recv;
297 } thunk32;
298#endif
299 int error, len;
300
311 dev = cdev->si_drv1;
312 sc = dev->ipmi_softc;
301 error = devfs_get_cdevpriv((void **)&dev);
302 if (error)
303 return (error);
313
304
305 sc = cdev->si_drv1;
306
314#ifdef IPMICTL_SEND_COMMAND_32
315 /* Convert 32-bit structures to native. */
316 switch (cmd) {
317 case IPMICTL_SEND_COMMAND_32:
318 req = &thunk32.req;
319 req->addr = PTRIN(req32->addr);
320 req->addr_len = req32->addr_len;
321 req->msgid = req32->msgid;

--- 332 unchanged lines hidden (view full) ---

654 timeout = ((uint64_t)1 << cmd) / 1800000000;
655 ipmi_set_watchdog(sc, timeout);
656 *error = 0;
657 } else {
658 ipmi_set_watchdog(sc, 0);
659 }
660}
661
307#ifdef IPMICTL_SEND_COMMAND_32
308 /* Convert 32-bit structures to native. */
309 switch (cmd) {
310 case IPMICTL_SEND_COMMAND_32:
311 req = &thunk32.req;
312 req->addr = PTRIN(req32->addr);
313 req->addr_len = req32->addr_len;
314 req->msgid = req32->msgid;

--- 332 unchanged lines hidden (view full) ---

647 timeout = ((uint64_t)1 << cmd) / 1800000000;
648 ipmi_set_watchdog(sc, timeout);
649 *error = 0;
650 } else {
651 ipmi_set_watchdog(sc, 0);
652 }
653}
654
662#ifdef CLONING
663static void
655static void
664ipmi_clone(void *arg, struct ucred *cred, char *name, int namelen,
665 struct cdev **cdev)
666{
667 struct ipmi_softc *sc = arg;
668 struct ipmi_device *dev;
669 int minor, unit;
670
671 if (*cdev != NULL)
672 return;
673
674 if (strcmp(name, device_get_nameunit(sc->ipmi_dev)) != 0)
675 return;
676
677 dev = malloc(sizeof(struct ipmi_device), M_IPMI, M_WAITOK | M_ZERO);
678
679 /* Reserve a sub-device. */
680 IPMI_LOCK(sc);
681 minor = ffs(~(sc->ipmi_cdev_mask & 0xffff));
682 if (minor == 0 || !sc->ipmi_cloning) {
683 IPMI_UNLOCK(sc);
684 free(dev, M_IPMI);
685 return;
686 }
687 minor--;
688 sc->ipmi_cdev_mask |= (1 << minor);
689 TAILQ_INSERT_TAIL(&sc->ipmi_cdevs, dev, ipmi_link);
690 IPMI_UNLOCK(sc);
691
692 /* Initialize the device. */
693 TAILQ_INIT(&dev->ipmi_completed_requests);
694 dev->ipmi_softc = sc;
695 dev->ipmi_address = IPMI_BMC_SLAVE_ADDR;
696 dev->ipmi_lun = IPMI_BMC_SMS_LUN;
697 unit = device_get_unit(sc->ipmi_dev);
698 dev->ipmi_cdev = make_dev_cred(&ipmi_cdevsw, unit * 32 + minor, cred,
699 UID_ROOT, GID_OPERATOR, 0660, "ipmi%d.%d", unit, minor);
700 if (dev->ipmi_cdev == NULL) {
701 IPMI_LOCK(sc);
702 sc->ipmi_cdev_mask &= ~(1 << minor);
703 TAILQ_REMOVE(&sc->ipmi_cdevs, dev, ipmi_link);
704 IPMI_UNLOCK(sc);
705 free(dev, M_IPMI);
706 return;
707 }
708 dev->ipmi_cdev->si_drv1 = dev;
709 *cdev = dev->ipmi_cdev;
710 dev_ref(*cdev);
711}
712#endif
713
714static void
715ipmi_startup(void *arg)
716{
717 struct ipmi_softc *sc = arg;
718 struct ipmi_request *req;
719 device_t dev;
720 int error, i;
721
722 config_intrhook_disestablish(&sc->ipmi_ich);
723 dev = sc->ipmi_dev;
724
725 /* Initialize interface-independent state. */
726 mtx_init(&sc->ipmi_lock, device_get_nameunit(dev), "ipmi", MTX_DEF);
727 cv_init(&sc->ipmi_request_added, "ipmireq");
728 TAILQ_INIT(&sc->ipmi_pending_requests);
656ipmi_startup(void *arg)
657{
658 struct ipmi_softc *sc = arg;
659 struct ipmi_request *req;
660 device_t dev;
661 int error, i;
662
663 config_intrhook_disestablish(&sc->ipmi_ich);
664 dev = sc->ipmi_dev;
665
666 /* Initialize interface-independent state. */
667 mtx_init(&sc->ipmi_lock, device_get_nameunit(dev), "ipmi", MTX_DEF);
668 cv_init(&sc->ipmi_request_added, "ipmireq");
669 TAILQ_INIT(&sc->ipmi_pending_requests);
729#ifdef CLONING
730 TAILQ_INIT(&sc->ipmi_cdevs);
731#endif
732
733 /* Initialize interface-dependent state. */
734 error = sc->ipmi_startup(sc);
735 if (error) {
736 device_printf(dev, "Failed to initialize interface: %d\n",
737 error);
738 return;
739 }

--- 70 unchanged lines hidden (view full) ---

810 if (req->ir_compcode == 0x00) {
811 device_printf(dev, "Attached watchdog\n");
812 /* register the watchdog event handler */
813 sc->ipmi_watchdog_tag = EVENTHANDLER_REGISTER(watchdog_list,
814 ipmi_wd_event, sc, 0);
815 }
816 ipmi_free_request(req);
817
670
671 /* Initialize interface-dependent state. */
672 error = sc->ipmi_startup(sc);
673 if (error) {
674 device_printf(dev, "Failed to initialize interface: %d\n",
675 error);
676 return;
677 }

--- 70 unchanged lines hidden (view full) ---

748 if (req->ir_compcode == 0x00) {
749 device_printf(dev, "Attached watchdog\n");
750 /* register the watchdog event handler */
751 sc->ipmi_watchdog_tag = EVENTHANDLER_REGISTER(watchdog_list,
752 ipmi_wd_event, sc, 0);
753 }
754 ipmi_free_request(req);
755
818#ifdef CLONING
819 sc->ipmi_cloning = 1;
820 sc->ipmi_clone_tag = EVENTHANDLER_REGISTER(dev_clone, ipmi_clone, sc,
821 1000);
822#else
823 /* Initialize the device. */
824 TAILQ_INIT(&sc->ipmi_idev.ipmi_completed_requests);
825 sc->ipmi_idev.ipmi_softc = sc;
826 sc->ipmi_idev.ipmi_address = IPMI_BMC_SLAVE_ADDR;
827 sc->ipmi_idev.ipmi_lun = IPMI_BMC_SMS_LUN;
828 sc->ipmi_idev.ipmi_cdev = make_dev(&ipmi_cdevsw, device_get_unit(dev),
756 sc->ipmi_cdev = make_dev(&ipmi_cdevsw, device_get_unit(dev),
829 UID_ROOT, GID_OPERATOR, 0660, "ipmi%d", device_get_unit(dev));
757 UID_ROOT, GID_OPERATOR, 0660, "ipmi%d", device_get_unit(dev));
830 if (sc->ipmi_idev.ipmi_cdev == NULL) {
758 if (sc->ipmi_cdev == NULL) {
831 device_printf(dev, "Failed to create cdev\n");
832 return;
833 }
759 device_printf(dev, "Failed to create cdev\n");
760 return;
761 }
834 sc->ipmi_idev.ipmi_cdev->si_drv1 = &sc->ipmi_idev;
835#endif
762 sc->ipmi_cdev->si_drv1 = sc;
836}
837
838int
839ipmi_attach(device_t dev)
840{
841 struct ipmi_softc *sc = device_get_softc(dev);
842 int error;
843

--- 22 unchanged lines hidden (view full) ---

866ipmi_detach(device_t dev)
867{
868 struct ipmi_softc *sc;
869
870 sc = device_get_softc(dev);
871
872 /* Fail if there are any open handles. */
873 IPMI_LOCK(sc);
763}
764
765int
766ipmi_attach(device_t dev)
767{
768 struct ipmi_softc *sc = device_get_softc(dev);
769 int error;
770

--- 22 unchanged lines hidden (view full) ---

793ipmi_detach(device_t dev)
794{
795 struct ipmi_softc *sc;
796
797 sc = device_get_softc(dev);
798
799 /* Fail if there are any open handles. */
800 IPMI_LOCK(sc);
874#ifdef CLONING
875 if (!TAILQ_EMPTY(&sc->ipmi_cdevs)) {
801 if (sc->ipmi_opened) {
876 IPMI_UNLOCK(sc);
877 return (EBUSY);
878 }
802 IPMI_UNLOCK(sc);
803 return (EBUSY);
804 }
879
880 /* Turn off cloning. */
881 sc->ipmi_cloning = 0;
882 IPMI_UNLOCK(sc);
805 IPMI_UNLOCK(sc);
806 if (sc->ipmi_cdev)
807 destroy_dev(sc->ipmi_cdev);
883
808
884 if (sc->ipmi_clone_tag)
885 EVENTHANDLER_DEREGISTER(dev_clone, sc->ipmi_clone_tag);
886#else
887 if (sc->ipmi_idev.ipmi_open) {
888 IPMI_UNLOCK(sc);
889 return (EBUSY);
890 }
891 IPMI_UNLOCK(sc);
892 if (sc->ipmi_idev.ipmi_cdev)
893 destroy_dev(sc->ipmi_idev.ipmi_cdev);
894#endif
895
896 /* Detach from watchdog handling and turn off watchdog. */
897 if (sc->ipmi_watchdog_tag) {
898 EVENTHANDLER_DEREGISTER(watchdog_list, sc->ipmi_watchdog_tag);
899 ipmi_set_watchdog(sc, 0);
900 }
901
902 /* XXX: should use shutdown callout I think. */
903 /* If the backend uses a kthread, shut it down. */

--- 90 unchanged lines hidden ---
809 /* Detach from watchdog handling and turn off watchdog. */
810 if (sc->ipmi_watchdog_tag) {
811 EVENTHANDLER_DEREGISTER(watchdog_list, sc->ipmi_watchdog_tag);
812 ipmi_set_watchdog(sc, 0);
813 }
814
815 /* XXX: should use shutdown callout I think. */
816 /* If the backend uses a kthread, shut it down. */

--- 90 unchanged lines hidden ---