2 * PowerNV OPAL IPMI driver
4 * Copyright 2014 IBM Corp.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
12 #define pr_fmt(fmt) "ipmi-powernv: " fmt
14 #include <linux/ipmi_smi.h>
15 #include <linux/list.h>
16 #include <linux/module.h>
18 #include <linux/of_irq.h>
19 #include <linux/interrupt.h>
24 struct ipmi_smi_powernv
{
26 struct ipmi_device_id ipmi_id
;
31 * We assume that there can only be one outstanding request, so
32 * keep the pending message in cur_msg. We protect this from concurrent
33 * updates through send & recv calls, (and consequently opal_msg, which
34 * is in-use when cur_msg is set) with msg_lock
37 struct ipmi_smi_msg
*cur_msg
;
38 struct opal_ipmi_msg
*opal_msg
;
41 static int ipmi_powernv_start_processing(void *send_info
, ipmi_smi_t intf
)
43 struct ipmi_smi_powernv
*smi
= send_info
;
49 static void send_error_reply(struct ipmi_smi_powernv
*smi
,
50 struct ipmi_smi_msg
*msg
, u8 completion_code
)
52 msg
->rsp
[0] = msg
->data
[0] | 0x4;
53 msg
->rsp
[1] = msg
->data
[1];
54 msg
->rsp
[2] = completion_code
;
56 ipmi_smi_msg_received(smi
->intf
, msg
);
59 static void ipmi_powernv_send(void *send_info
, struct ipmi_smi_msg
*msg
)
61 struct ipmi_smi_powernv
*smi
= send_info
;
62 struct opal_ipmi_msg
*opal_msg
;
67 /* ensure data_len will fit in the opal_ipmi_msg buffer... */
68 if (msg
->data_size
> IPMI_MAX_MSG_LENGTH
) {
69 comp
= IPMI_REQ_LEN_EXCEEDED_ERR
;
73 /* ... and that we at least have netfn and cmd bytes */
74 if (msg
->data_size
< 2) {
75 comp
= IPMI_REQ_LEN_INVALID_ERR
;
79 spin_lock_irqsave(&smi
->msg_lock
, flags
);
82 comp
= IPMI_NODE_BUSY_ERR
;
86 /* format our data for the OPAL API */
87 opal_msg
= smi
->opal_msg
;
88 opal_msg
->version
= OPAL_IPMI_MSG_FORMAT_VERSION_1
;
89 opal_msg
->netfn
= msg
->data
[0];
90 opal_msg
->cmd
= msg
->data
[1];
91 if (msg
->data_size
> 2)
92 memcpy(opal_msg
->data
, msg
->data
+ 2, msg
->data_size
- 2);
94 /* data_size already includes the netfn and cmd bytes */
95 size
= sizeof(*opal_msg
) + msg
->data_size
- 2;
97 pr_devel("%s: opal_ipmi_send(0x%llx, %p, %ld)\n", __func__
,
98 smi
->interface_id
, opal_msg
, size
);
99 rc
= opal_ipmi_send(smi
->interface_id
, opal_msg
, size
);
100 pr_devel("%s: -> %d\n", __func__
, rc
);
104 spin_unlock_irqrestore(&smi
->msg_lock
, flags
);
108 comp
= IPMI_ERR_UNSPECIFIED
;
110 spin_unlock_irqrestore(&smi
->msg_lock
, flags
);
112 send_error_reply(smi
, msg
, comp
);
115 static int ipmi_powernv_recv(struct ipmi_smi_powernv
*smi
)
117 struct opal_ipmi_msg
*opal_msg
;
118 struct ipmi_smi_msg
*msg
;
123 pr_devel("%s: opal_ipmi_recv(%llx, msg, sz)\n", __func__
,
126 spin_lock_irqsave(&smi
->msg_lock
, flags
);
129 spin_unlock_irqrestore(&smi
->msg_lock
, flags
);
130 pr_warn("no current message?\n");
135 opal_msg
= smi
->opal_msg
;
137 size
= cpu_to_be64(sizeof(*opal_msg
) + IPMI_MAX_MSG_LENGTH
);
139 rc
= opal_ipmi_recv(smi
->interface_id
,
142 size
= be64_to_cpu(size
);
143 pr_devel("%s: -> %d (size %lld)\n", __func__
,
144 rc
, rc
== 0 ? size
: 0);
146 /* If came via the poll, and response was not yet ready */
147 if (rc
== OPAL_EMPTY
) {
148 spin_unlock_irqrestore(&smi
->msg_lock
, flags
);
153 spin_unlock_irqrestore(&smi
->msg_lock
, flags
);
154 send_error_reply(smi
, msg
, IPMI_ERR_UNSPECIFIED
);
158 if (size
< sizeof(*opal_msg
)) {
159 spin_unlock_irqrestore(&smi
->msg_lock
, flags
);
160 pr_warn("unexpected IPMI message size %lld\n", size
);
164 if (opal_msg
->version
!= OPAL_IPMI_MSG_FORMAT_VERSION_1
) {
165 spin_unlock_irqrestore(&smi
->msg_lock
, flags
);
166 pr_warn("unexpected IPMI message format (version %d)\n",
171 msg
->rsp
[0] = opal_msg
->netfn
;
172 msg
->rsp
[1] = opal_msg
->cmd
;
173 if (size
> sizeof(*opal_msg
))
174 memcpy(&msg
->rsp
[2], opal_msg
->data
, size
- sizeof(*opal_msg
));
175 msg
->rsp_size
= 2 + size
- sizeof(*opal_msg
);
178 spin_unlock_irqrestore(&smi
->msg_lock
, flags
);
179 ipmi_smi_msg_received(smi
->intf
, msg
);
183 static void ipmi_powernv_request_events(void *send_info
)
187 static void ipmi_powernv_set_run_to_completion(void *send_info
,
188 bool run_to_completion
)
192 static void ipmi_powernv_poll(void *send_info
)
194 struct ipmi_smi_powernv
*smi
= send_info
;
196 ipmi_powernv_recv(smi
);
199 static struct ipmi_smi_handlers ipmi_powernv_smi_handlers
= {
200 .owner
= THIS_MODULE
,
201 .start_processing
= ipmi_powernv_start_processing
,
202 .sender
= ipmi_powernv_send
,
203 .request_events
= ipmi_powernv_request_events
,
204 .set_run_to_completion
= ipmi_powernv_set_run_to_completion
,
205 .poll
= ipmi_powernv_poll
,
208 static irqreturn_t
ipmi_opal_event(int irq
, void *data
)
210 struct ipmi_smi_powernv
*smi
= data
;
212 ipmi_powernv_recv(smi
);
216 static int ipmi_powernv_probe(struct platform_device
*pdev
)
218 struct ipmi_smi_powernv
*ipmi
;
223 if (!pdev
|| !pdev
->dev
.of_node
)
228 ipmi
= devm_kzalloc(dev
, sizeof(*ipmi
), GFP_KERNEL
);
232 spin_lock_init(&ipmi
->msg_lock
);
234 rc
= of_property_read_u32(dev
->of_node
, "ibm,ipmi-interface-id",
237 dev_warn(dev
, "No interface ID property\n");
240 ipmi
->interface_id
= prop
;
242 rc
= of_property_read_u32(dev
->of_node
, "interrupts", &prop
);
244 dev_warn(dev
, "No interrupts property\n");
248 ipmi
->irq
= irq_of_parse_and_map(dev
->of_node
, 0);
250 dev_info(dev
, "Unable to map irq from device tree\n");
251 ipmi
->irq
= opal_event_request(prop
);
254 if (request_irq(ipmi
->irq
, ipmi_opal_event
, IRQ_TYPE_LEVEL_HIGH
,
255 "opal-ipmi", ipmi
)) {
256 dev_warn(dev
, "Unable to request irq\n");
260 ipmi
->opal_msg
= devm_kmalloc(dev
,
261 sizeof(*ipmi
->opal_msg
) + IPMI_MAX_MSG_LENGTH
,
263 if (!ipmi
->opal_msg
) {
268 /* todo: query actual ipmi_device_id */
269 rc
= ipmi_register_smi(&ipmi_powernv_smi_handlers
, ipmi
,
270 &ipmi
->ipmi_id
, dev
, 0);
272 dev_warn(dev
, "IPMI SMI registration failed (%d)\n", rc
);
276 dev_set_drvdata(dev
, ipmi
);
280 devm_kfree(dev
, ipmi
->opal_msg
);
282 free_irq(ipmi
->irq
, ipmi
);
284 irq_dispose_mapping(ipmi
->irq
);
286 devm_kfree(dev
, ipmi
);
290 static int ipmi_powernv_remove(struct platform_device
*pdev
)
292 struct ipmi_smi_powernv
*smi
= dev_get_drvdata(&pdev
->dev
);
294 ipmi_unregister_smi(smi
->intf
);
295 free_irq(smi
->irq
, smi
);
296 irq_dispose_mapping(smi
->irq
);
301 static const struct of_device_id ipmi_powernv_match
[] = {
302 { .compatible
= "ibm,opal-ipmi" },
307 static struct platform_driver powernv_ipmi_driver
= {
309 .name
= "ipmi-powernv",
310 .of_match_table
= ipmi_powernv_match
,
312 .probe
= ipmi_powernv_probe
,
313 .remove
= ipmi_powernv_remove
,
317 module_platform_driver(powernv_ipmi_driver
);
319 MODULE_DEVICE_TABLE(of
, ipmi_powernv_match
);
320 MODULE_DESCRIPTION("powernv IPMI driver");
321 MODULE_AUTHOR("Jeremy Kerr <jk@ozlabs.org>");
322 MODULE_LICENSE("GPL");