Deleted Added
sdiff udiff text old ( 167950 ) new ( 182322 )
full compact
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 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;
61static void ipmi_dtor(void *arg);
62
63int ipmi_attached = 0;
64
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,
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;
86
87 if (!on)
88 return (ENOENT);
89
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);
96 }
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++;
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
117 if (devfs_get_cdevpriv((void **)&dev))
118 return (0);
119
120 sc = cdev->si_drv1;
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
151static void
152ipmi_dtor(void *arg)
153{
154 struct ipmi_request *req, *nreq;
155 struct ipmi_device *dev;
156 struct ipmi_softc *sc;
157
158 dev = arg;
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 }
188 sc->ipmi_opened--;
189 IPMI_UNLOCK(sc);
190
191 /* Cleanup. */
192 free(dev, M_IPMI);
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
301 error = devfs_get_cdevpriv((void **)&dev);
302 if (error)
303 return (error);
304
305 sc = cdev->si_drv1;
306
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
655static void
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);
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
756 sc->ipmi_cdev = make_dev(&ipmi_cdevsw, device_get_unit(dev),
757 UID_ROOT, GID_OPERATOR, 0660, "ipmi%d", device_get_unit(dev));
758 if (sc->ipmi_cdev == NULL) {
759 device_printf(dev, "Failed to create cdev\n");
760 return;
761 }
762 sc->ipmi_cdev->si_drv1 = 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);
801 if (sc->ipmi_opened) {
802 IPMI_UNLOCK(sc);
803 return (EBUSY);
804 }
805 IPMI_UNLOCK(sc);
806 if (sc->ipmi_cdev)
807 destroy_dev(sc->ipmi_cdev);
808
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 ---