aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/misc/Kconfig13
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/hpilo.c768
-rw-r--r--drivers/misc/hpilo.h189
4 files changed, 971 insertions, 0 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 1921b8dbb242..ce67d973d349 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -420,4 +420,17 @@ config SGI_XP
420 this feature will allow for direct communication between SSIs 420 this feature will allow for direct communication between SSIs
421 based on a network adapter and DMA messaging. 421 based on a network adapter and DMA messaging.
422 422
423config HP_ILO
424 tristate "Channel interface driver for HP iLO/iLO2 processor"
425 default n
426 help
427 The channel interface driver allows applications to communicate
428 with iLO/iLO2 management processors present on HP ProLiant
429 servers. Upon loading, the driver creates /dev/hpilo/dXccbN files,
430 which can be used to gather data from the management processor,
431 via read and write system calls.
432
433 To compile this driver as a module, choose M here: the
434 module will be called hpilo.
435
423endif # MISC_DEVICES 436endif # MISC_DEVICES
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index a6dac6a2e7e5..688fe76135e0 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -27,3 +27,4 @@ obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
27obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o 27obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
28obj-$(CONFIG_KGDB_TESTS) += kgdbts.o 28obj-$(CONFIG_KGDB_TESTS) += kgdbts.o
29obj-$(CONFIG_SGI_XP) += sgi-xp/ 29obj-$(CONFIG_SGI_XP) += sgi-xp/
30obj-$(CONFIG_HP_ILO) += hpilo.o
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c
new file mode 100644
index 000000000000..05e298289238
--- /dev/null
+++ b/drivers/misc/hpilo.c
@@ -0,0 +1,768 @@
1/*
2 * Driver for HP iLO/iLO2 management processor.
3 *
4 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
5 * David Altobelli <david.altobelli@hp.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include <linux/kernel.h>
12#include <linux/types.h>
13#include <linux/module.h>
14#include <linux/fs.h>
15#include <linux/pci.h>
16#include <linux/ioport.h>
17#include <linux/device.h>
18#include <linux/file.h>
19#include <linux/cdev.h>
20#include <linux/spinlock.h>
21#include <linux/delay.h>
22#include <linux/uaccess.h>
23#include <linux/io.h>
24#include "hpilo.h"
25
26static struct class *ilo_class;
27static unsigned int ilo_major;
28static char ilo_hwdev[MAX_ILO_DEV];
29
30static inline int get_entry_id(int entry)
31{
32 return (entry & ENTRY_MASK_DESCRIPTOR) >> ENTRY_BITPOS_DESCRIPTOR;
33}
34
35static inline int get_entry_len(int entry)
36{
37 return ((entry & ENTRY_MASK_QWORDS) >> ENTRY_BITPOS_QWORDS) << 3;
38}
39
40static inline int mk_entry(int id, int len)
41{
42 int qlen = len & 7 ? (len >> 3) + 1 : len >> 3;
43 return id << ENTRY_BITPOS_DESCRIPTOR | qlen << ENTRY_BITPOS_QWORDS;
44}
45
46static inline int desc_mem_sz(int nr_entry)
47{
48 return nr_entry << L2_QENTRY_SZ;
49}
50
51/*
52 * FIFO queues, shared with hardware.
53 *
54 * If a queue has empty slots, an entry is added to the queue tail,
55 * and that entry is marked as occupied.
56 * Entries can be dequeued from the head of the list, when the device
57 * has marked the entry as consumed.
58 *
59 * Returns true on successful queue/dequeue, false on failure.
60 */
61static int fifo_enqueue(struct ilo_hwinfo *hw, char *fifobar, int entry)
62{
63 struct fifo *fifo_q = FIFOBARTOHANDLE(fifobar);
64 int ret = 0;
65
66 spin_lock(&hw->fifo_lock);
67 if (!(fifo_q->fifobar[(fifo_q->tail + 1) & fifo_q->imask]
68 & ENTRY_MASK_O)) {
69 fifo_q->fifobar[fifo_q->tail & fifo_q->imask] |=
70 (entry & ENTRY_MASK_NOSTATE) | fifo_q->merge;
71 fifo_q->tail += 1;
72 ret = 1;
73 }
74 spin_unlock(&hw->fifo_lock);
75
76 return ret;
77}
78
79static int fifo_dequeue(struct ilo_hwinfo *hw, char *fifobar, int *entry)
80{
81 struct fifo *fifo_q = FIFOBARTOHANDLE(fifobar);
82 int ret = 0;
83 u64 c;
84
85 spin_lock(&hw->fifo_lock);
86 c = fifo_q->fifobar[fifo_q->head & fifo_q->imask];
87 if (c & ENTRY_MASK_C) {
88 if (entry)
89 *entry = c & ENTRY_MASK_NOSTATE;
90
91 fifo_q->fifobar[fifo_q->head & fifo_q->imask] =
92 (c | ENTRY_MASK) + 1;
93 fifo_q->head += 1;
94 ret = 1;
95 }
96 spin_unlock(&hw->fifo_lock);
97
98 return ret;
99}
100
101static int ilo_pkt_enqueue(struct ilo_hwinfo *hw, struct ccb *ccb,
102 int dir, int id, int len)
103{
104 char *fifobar;
105 int entry;
106
107 if (dir == SENDQ)
108 fifobar = ccb->ccb_u1.send_fifobar;
109 else
110 fifobar = ccb->ccb_u3.recv_fifobar;
111
112 entry = mk_entry(id, len);
113 return fifo_enqueue(hw, fifobar, entry);
114}
115
116static int ilo_pkt_dequeue(struct ilo_hwinfo *hw, struct ccb *ccb,
117 int dir, int *id, int *len, void **pkt)
118{
119 char *fifobar, *desc;
120 int entry = 0, pkt_id = 0;
121 int ret;
122
123 if (dir == SENDQ) {
124 fifobar = ccb->ccb_u1.send_fifobar;
125 desc = ccb->ccb_u2.send_desc;
126 } else {
127 fifobar = ccb->ccb_u3.recv_fifobar;
128 desc = ccb->ccb_u4.recv_desc;
129 }
130
131 ret = fifo_dequeue(hw, fifobar, &entry);
132 if (ret) {
133 pkt_id = get_entry_id(entry);
134 if (id)
135 *id = pkt_id;
136 if (len)
137 *len = get_entry_len(entry);
138 if (pkt)
139 *pkt = (void *)(desc + desc_mem_sz(pkt_id));
140 }
141
142 return ret;
143}
144
145static inline void doorbell_set(struct ccb *ccb)
146{
147 iowrite8(1, ccb->ccb_u5.db_base);
148}
149
150static inline void doorbell_clr(struct ccb *ccb)
151{
152 iowrite8(2, ccb->ccb_u5.db_base);
153}
154static inline int ctrl_set(int l2sz, int idxmask, int desclim)
155{
156 int active = 0, go = 1;
157 return l2sz << CTRL_BITPOS_L2SZ |
158 idxmask << CTRL_BITPOS_FIFOINDEXMASK |
159 desclim << CTRL_BITPOS_DESCLIMIT |
160 active << CTRL_BITPOS_A |
161 go << CTRL_BITPOS_G;
162}
163static void ctrl_setup(struct ccb *ccb, int nr_desc, int l2desc_sz)
164{
165 /* for simplicity, use the same parameters for send and recv ctrls */
166 ccb->send_ctrl = ctrl_set(l2desc_sz, nr_desc-1, nr_desc-1);
167 ccb->recv_ctrl = ctrl_set(l2desc_sz, nr_desc-1, nr_desc-1);
168}
169
170static inline int fifo_sz(int nr_entry)
171{
172 /* size of a fifo is determined by the number of entries it contains */
173 return (nr_entry * sizeof(u64)) + FIFOHANDLESIZE;
174}
175