1 /* ds.c: Domain Services driver for Logical Domains
3 * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
6 #include <linux/kernel.h>
7 #include <linux/module.h>
8 #include <linux/types.h>
9 #include <linux/module.h>
10 #include <linux/string.h>
11 #include <linux/slab.h>
12 #include <linux/sched.h>
13 #include <linux/delay.h>
17 #include <asm/power.h>
19 #define DRV_MODULE_NAME "ds"
20 #define PFX DRV_MODULE_NAME ": "
21 #define DRV_MODULE_VERSION "1.0"
22 #define DRV_MODULE_RELDATE "Jul 11, 2007"
24 static char version[] __devinitdata =
25 DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
26 MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
27 MODULE_DESCRIPTION("Sun LDOM domain services driver");
28 MODULE_LICENSE("GPL");
29 MODULE_VERSION(DRV_MODULE_VERSION);
33 #define DS_INIT_REQ 0x00
34 #define DS_INIT_ACK 0x01
35 #define DS_INIT_NACK 0x02
36 #define DS_REG_REQ 0x03
37 #define DS_REG_ACK 0x04
38 #define DS_REG_NACK 0x05
39 #define DS_UNREG_REQ 0x06
40 #define DS_UNREG_ACK 0x07
41 #define DS_UNREG_NACK 0x08
50 #define DS_REG_VER_NACK 0x01
51 #define DS_REG_DUP 0x02
52 #define DS_INV_HDL 0x03
53 #define DS_TYPE_UNKNOWN 0x04
61 struct ds_msg_tag tag;
62 struct ds_version ver;
66 struct ds_msg_tag tag;
71 struct ds_msg_tag tag;
76 struct ds_msg_tag tag;
84 struct ds_msg_tag tag;
90 struct ds_msg_tag tag;
96 struct ds_msg_tag tag;
100 struct ds_unreg_ack {
101 struct ds_msg_tag tag;
105 struct ds_unreg_nack {
106 struct ds_msg_tag tag;
111 struct ds_msg_tag tag;
115 struct ds_data_nack {
116 struct ds_msg_tag tag;
121 struct ds_cap_state {
124 void (*data)(struct ldc_channel *lp,
125 struct ds_cap_state *dp,
128 const char *service_id;
131 #define CAP_STATE_UNKNOWN 0x00
132 #define CAP_STATE_REG_SENT 0x01
133 #define CAP_STATE_REGISTERED 0x02
136 static int ds_send(struct ldc_channel *lp, void *data, int len)
138 int err, limit = 1000;
141 while (limit-- > 0) {
142 err = ldc_write(lp, data, len);
143 if (!err || (err != -EAGAIN))
151 struct ds_md_update_req {
155 struct ds_md_update_res {
160 static void md_update_data(struct ldc_channel *lp,
161 struct ds_cap_state *dp,
164 struct ds_data *dpkt = buf;
165 struct ds_md_update_req *rp;
168 struct ds_md_update_res res;
171 rp = (struct ds_md_update_req *) (dpkt + 1);
173 printk(KERN_ERR PFX "MD update REQ [%lx] len=%d\n",
176 memset(&pkt, 0, sizeof(pkt));
177 pkt.data.tag.type = DS_DATA;
178 pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
179 pkt.data.handle = dp->handle;
180 pkt.res.req_num = rp->req_num;
181 pkt.res.result = DS_OK;
183 ds_send(lp, &pkt, sizeof(pkt));
186 struct ds_shutdown_req {
191 struct ds_shutdown_res {
197 static void domain_shutdown_data(struct ldc_channel *lp,
198 struct ds_cap_state *dp,
201 struct ds_data *dpkt = buf;
202 struct ds_shutdown_req *rp;
205 struct ds_shutdown_res res;
208 rp = (struct ds_shutdown_req *) (dpkt + 1);
210 printk(KERN_ALERT PFX "Shutdown request from "
211 "LDOM manager received.\n");
213 memset(&pkt, 0, sizeof(pkt));
214 pkt.data.tag.type = DS_DATA;
215 pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
216 pkt.data.handle = dp->handle;
217 pkt.res.req_num = rp->req_num;
218 pkt.res.result = DS_OK;
219 pkt.res.reason[0] = 0;
221 ds_send(lp, &pkt, sizeof(pkt));
226 struct ds_panic_req {
230 struct ds_panic_res {
236 static void domain_panic_data(struct ldc_channel *lp,
237 struct ds_cap_state *dp,
240 struct ds_data *dpkt = buf;
241 struct ds_panic_req *rp;
244 struct ds_panic_res res;
247 rp = (struct ds_panic_req *) (dpkt + 1);
249 printk(KERN_ERR PFX "Panic REQ [%lx], len=%d\n",
252 memset(&pkt, 0, sizeof(pkt));
253 pkt.data.tag.type = DS_DATA;
254 pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
255 pkt.data.handle = dp->handle;
256 pkt.res.req_num = rp->req_num;
257 pkt.res.result = DS_OK;
258 pkt.res.reason[0] = 0;
260 ds_send(lp, &pkt, sizeof(pkt));
262 panic("PANIC requested by LDOM manager.");
268 #define DS_CPU_CONFIGURE 0x43
269 #define DS_CPU_UNCONFIGURE 0x55
270 #define DS_CPU_FORCE_UNCONFIGURE 0x46
271 #define DS_CPU_STATUS 0x53
274 #define DS_CPU_OK 0x6f
275 #define DS_CPU_ERROR 0x65
280 struct ds_cpu_record {
284 static void dr_cpu_data(struct ldc_channel *lp,
285 struct ds_cap_state *dp,
288 struct ds_data *dpkt = buf;
289 struct ds_cpu_tag *rp;
291 rp = (struct ds_cpu_tag *) (dpkt + 1);
293 printk(KERN_ERR PFX "CPU REQ [%lx:%x], len=%d\n",
294 rp->req_num, rp->type, len);
300 #define DS_PRI_REQUEST 0x00
301 #define DS_PRI_DATA 0x01
302 #define DS_PRI_UPDATE 0x02
305 static void ds_pri_data(struct ldc_channel *lp,
306 struct ds_cap_state *dp,
309 struct ds_data *dpkt = buf;
310 struct ds_pri_msg *rp;
312 rp = (struct ds_pri_msg *) (dpkt + 1);
314 printk(KERN_ERR PFX "PRI REQ [%lx:%lx], len=%d\n",
315 rp->req_num, rp->type, len);
318 struct ds_cap_state ds_states[] = {
320 .service_id = "md-update",
321 .data = md_update_data,
324 .service_id = "domain-shutdown",
325 .data = domain_shutdown_data,
328 .service_id = "domain-panic",
329 .data = domain_panic_data,
332 .service_id = "dr-cpu",
341 static struct ds_cap_state *find_cap(u64 handle)
343 unsigned int index = handle >> 32;
345 if (index >= ARRAY_SIZE(ds_states))
347 return &ds_states[index];
350 static DEFINE_SPINLOCK(ds_lock);
353 struct ldc_channel *lp;
355 #define DS_HS_START 0x01
356 #define DS_HS_DONE 0x02
362 static void ds_conn_reset(struct ds_info *dp)
364 printk(KERN_ERR PFX "ds_conn_reset() from %p\n",
365 __builtin_return_address(0));
368 static int register_services(struct ds_info *dp)
370 struct ldc_channel *lp = dp->lp;
373 for (i = 0; i < ARRAY_SIZE(ds_states); i++) {
375 struct ds_reg_req req;
378 struct ds_cap_state *cp = &ds_states[i];
382 if (cp->state == CAP_STATE_REGISTERED)
385 new_count = sched_clock() & 0xffffffff;
386 cp->handle = ((u64) i << 32) | new_count;
388 msg_len = (sizeof(struct ds_reg_req) +
389 strlen(cp->service_id));
391 memset(&pbuf, 0, sizeof(pbuf));
392 pbuf.req.tag.type = DS_REG_REQ;
393 pbuf.req.tag.len = (msg_len - sizeof(struct ds_msg_tag));
394 pbuf.req.handle = cp->handle;
397 strcpy(pbuf.req.svc_id, cp->service_id);
399 err = ds_send(lp, &pbuf, msg_len);
401 cp->state = CAP_STATE_REG_SENT;
406 static int ds_handshake(struct ds_info *dp, struct ds_msg_tag *pkt)
409 if (dp->hs_state == DS_HS_START) {
410 if (pkt->type != DS_INIT_ACK)
413 dp->hs_state = DS_HS_DONE;
415 return register_services(dp);
418 if (dp->hs_state != DS_HS_DONE)
421 if (pkt->type == DS_REG_ACK) {
422 struct ds_reg_ack *ap = (struct ds_reg_ack *) pkt;
423 struct ds_cap_state *cp = find_cap(ap->handle);
426 printk(KERN_ERR PFX "REG ACK for unknown handle %lx\n",
430 printk(KERN_INFO PFX "Registered %s service.\n",
432 cp->state = CAP_STATE_REGISTERED;
433 } else if (pkt->type == DS_REG_NACK) {
434 struct ds_reg_nack *np = (struct ds_reg_nack *) pkt;
435 struct ds_cap_state *cp = find_cap(np->handle);
438 printk(KERN_ERR PFX "REG NACK for "
439 "unknown handle %lx\n",
443 printk(KERN_ERR PFX "Could not register %s service\n",
445 cp->state = CAP_STATE_UNKNOWN;
455 static int ds_data(struct ds_info *dp, struct ds_msg_tag *pkt, int len)
457 struct ds_data *dpkt = (struct ds_data *) pkt;
458 struct ds_cap_state *cp = find_cap(dpkt->handle);
461 struct ds_data_nack nack = {
464 .len = (sizeof(struct ds_data_nack) -
465 sizeof(struct ds_msg_tag)),
467 .handle = dpkt->handle,
468 .result = DS_INV_HDL,
471 printk(KERN_ERR PFX "Data for unknown handle %lu\n",
473 ds_send(dp->lp, &nack, sizeof(nack));
475 cp->data(dp->lp, cp, dpkt, len);
480 static void ds_up(struct ds_info *dp)
482 struct ldc_channel *lp = dp->lp;
483 struct ds_ver_req req;
486 req.tag.type = DS_INIT_REQ;
487 req.tag.len = sizeof(req) - sizeof(struct ds_msg_tag);
491 err = ds_send(lp, &req, sizeof(req));
493 dp->hs_state = DS_HS_START;
496 static void ds_event(void *arg, int event)
498 struct ds_info *dp = arg;
499 struct ldc_channel *lp = dp->lp;
503 spin_lock_irqsave(&ds_lock, flags);
505 if (event == LDC_EVENT_UP) {
507 spin_unlock_irqrestore(&ds_lock, flags);
511 if (event != LDC_EVENT_DATA_READY) {
512 printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event);
513 spin_unlock_irqrestore(&ds_lock, flags);
519 struct ds_msg_tag *tag;
521 err = ldc_read(lp, dp->rcv_buf, sizeof(*tag));
523 if (unlikely(err < 0)) {
524 if (err == -ECONNRESET)
532 err = ldc_read(lp, tag + 1, tag->len);
534 if (unlikely(err < 0)) {
535 if (err == -ECONNRESET)
542 if (tag->type < DS_DATA)
543 err = ds_handshake(dp, dp->rcv_buf);
545 err = ds_data(dp, dp->rcv_buf,
547 if (err == -ECONNRESET)
551 spin_unlock_irqrestore(&ds_lock, flags);
554 static int __devinit ds_probe(struct vio_dev *vdev,
555 const struct vio_device_id *id)
557 static int ds_version_printed;
558 struct mdesc_node *endp;
559 struct ldc_channel_config ds_cfg = {
562 .mode = LDC_MODE_STREAM,
564 struct ldc_channel *lp;
569 if (ds_version_printed++ == 0)
570 printk(KERN_INFO "%s", version);
572 endp = vio_find_endpoint(vdev);
576 chan_id = md_get_property(endp, "id", NULL);
580 dp = kzalloc(sizeof(*dp), GFP_KERNEL);
585 dp->rcv_buf = kzalloc(4096, GFP_KERNEL);
589 dp->rcv_buf_len = 4096;
591 ds_cfg.tx_irq = endp->irqs[0];
592 ds_cfg.rx_irq = endp->irqs[1];
594 lp = ldc_alloc(*chan_id, &ds_cfg, dp);
597 goto out_free_rcv_buf;
622 static int ds_remove(struct vio_dev *vdev)
627 static struct vio_device_id ds_match[] = {
629 .type = "domain-services-port",
634 static struct vio_driver ds_driver = {
635 .id_table = ds_match,
640 .owner = THIS_MODULE,
644 static int __init ds_init(void)
648 for (i = 0; i < ARRAY_SIZE(ds_states); i++)
649 ds_states[i].handle = ((u64)i << 32);
651 return vio_register_driver(&ds_driver);
654 subsys_initcall(ds_init);