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>
18 #include <asm/mdesc.h>
20 #define DRV_MODULE_NAME "ds"
21 #define PFX DRV_MODULE_NAME ": "
22 #define DRV_MODULE_VERSION "1.0"
23 #define DRV_MODULE_RELDATE "Jul 11, 2007"
25 static char version[] __devinitdata =
26 DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
27 MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
28 MODULE_DESCRIPTION("Sun LDOM domain services driver");
29 MODULE_LICENSE("GPL");
30 MODULE_VERSION(DRV_MODULE_VERSION);
34 #define DS_INIT_REQ 0x00
35 #define DS_INIT_ACK 0x01
36 #define DS_INIT_NACK 0x02
37 #define DS_REG_REQ 0x03
38 #define DS_REG_ACK 0x04
39 #define DS_REG_NACK 0x05
40 #define DS_UNREG_REQ 0x06
41 #define DS_UNREG_ACK 0x07
42 #define DS_UNREG_NACK 0x08
51 #define DS_REG_VER_NACK 0x01
52 #define DS_REG_DUP 0x02
53 #define DS_INV_HDL 0x03
54 #define DS_TYPE_UNKNOWN 0x04
62 struct ds_msg_tag tag;
63 struct ds_version ver;
67 struct ds_msg_tag tag;
72 struct ds_msg_tag tag;
77 struct ds_msg_tag tag;
85 struct ds_msg_tag tag;
91 struct ds_msg_tag tag;
97 struct ds_msg_tag tag;
101 struct ds_unreg_ack {
102 struct ds_msg_tag tag;
106 struct ds_unreg_nack {
107 struct ds_msg_tag tag;
112 struct ds_msg_tag tag;
116 struct ds_data_nack {
117 struct ds_msg_tag tag;
122 struct ds_cap_state {
125 void (*data)(struct ldc_channel *lp,
126 struct ds_cap_state *dp,
129 const char *service_id;
132 #define CAP_STATE_UNKNOWN 0x00
133 #define CAP_STATE_REG_SENT 0x01
134 #define CAP_STATE_REGISTERED 0x02
137 static int ds_send(struct ldc_channel *lp, void *data, int len)
139 int err, limit = 1000;
142 while (limit-- > 0) {
143 err = ldc_write(lp, data, len);
144 if (!err || (err != -EAGAIN))
152 struct ds_md_update_req {
156 struct ds_md_update_res {
161 static void md_update_data(struct ldc_channel *lp,
162 struct ds_cap_state *dp,
165 struct ds_data *dpkt = buf;
166 struct ds_md_update_req *rp;
169 struct ds_md_update_res res;
172 rp = (struct ds_md_update_req *) (dpkt + 1);
174 printk(KERN_ERR PFX "Machine description update.\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));
188 struct ds_shutdown_req {
193 struct ds_shutdown_res {
199 static void domain_shutdown_data(struct ldc_channel *lp,
200 struct ds_cap_state *dp,
203 struct ds_data *dpkt = buf;
204 struct ds_shutdown_req *rp;
207 struct ds_shutdown_res res;
210 rp = (struct ds_shutdown_req *) (dpkt + 1);
212 printk(KERN_ALERT PFX "Shutdown request from "
213 "LDOM manager received.\n");
215 memset(&pkt, 0, sizeof(pkt));
216 pkt.data.tag.type = DS_DATA;
217 pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
218 pkt.data.handle = dp->handle;
219 pkt.res.req_num = rp->req_num;
220 pkt.res.result = DS_OK;
221 pkt.res.reason[0] = 0;
223 ds_send(lp, &pkt, sizeof(pkt));
228 struct ds_panic_req {
232 struct ds_panic_res {
238 static void domain_panic_data(struct ldc_channel *lp,
239 struct ds_cap_state *dp,
242 struct ds_data *dpkt = buf;
243 struct ds_panic_req *rp;
246 struct ds_panic_res res;
249 rp = (struct ds_panic_req *) (dpkt + 1);
251 printk(KERN_ERR PFX "Panic REQ [%lx], len=%d\n",
254 memset(&pkt, 0, sizeof(pkt));
255 pkt.data.tag.type = DS_DATA;
256 pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
257 pkt.data.handle = dp->handle;
258 pkt.res.req_num = rp->req_num;
259 pkt.res.result = DS_OK;
260 pkt.res.reason[0] = 0;
262 ds_send(lp, &pkt, sizeof(pkt));
264 panic("PANIC requested by LDOM manager.");
270 #define DS_CPU_CONFIGURE 0x43
271 #define DS_CPU_UNCONFIGURE 0x55
272 #define DS_CPU_FORCE_UNCONFIGURE 0x46
273 #define DS_CPU_STATUS 0x53
276 #define DS_CPU_OK 0x6f
277 #define DS_CPU_ERROR 0x65
282 struct ds_cpu_record {
286 static void dr_cpu_data(struct ldc_channel *lp,
287 struct ds_cap_state *dp,
290 struct ds_data *dpkt = buf;
291 struct ds_cpu_tag *rp;
293 rp = (struct ds_cpu_tag *) (dpkt + 1);
295 printk(KERN_ERR PFX "CPU REQ [%lx:%x], len=%d\n",
296 rp->req_num, rp->type, len);
302 #define DS_PRI_REQUEST 0x00
303 #define DS_PRI_DATA 0x01
304 #define DS_PRI_UPDATE 0x02
307 static void ds_pri_data(struct ldc_channel *lp,
308 struct ds_cap_state *dp,
311 struct ds_data *dpkt = buf;
312 struct ds_pri_msg *rp;
314 rp = (struct ds_pri_msg *) (dpkt + 1);
316 printk(KERN_ERR PFX "PRI REQ [%lx:%lx], len=%d\n",
317 rp->req_num, rp->type, len);
320 struct ds_cap_state ds_states[] = {
322 .service_id = "md-update",
323 .data = md_update_data,
326 .service_id = "domain-shutdown",
327 .data = domain_shutdown_data,
330 .service_id = "domain-panic",
331 .data = domain_panic_data,
334 .service_id = "dr-cpu",
343 static struct ds_cap_state *find_cap(u64 handle)
345 unsigned int index = handle >> 32;
347 if (index >= ARRAY_SIZE(ds_states))
349 return &ds_states[index];
352 static DEFINE_SPINLOCK(ds_lock);
355 struct ldc_channel *lp;
357 #define DS_HS_START 0x01
358 #define DS_HS_DONE 0x02
364 static void ds_conn_reset(struct ds_info *dp)
366 printk(KERN_ERR PFX "ds_conn_reset() from %p\n",
367 __builtin_return_address(0));
370 static int register_services(struct ds_info *dp)
372 struct ldc_channel *lp = dp->lp;
375 for (i = 0; i < ARRAY_SIZE(ds_states); i++) {
377 struct ds_reg_req req;
380 struct ds_cap_state *cp = &ds_states[i];
384 if (cp->state == CAP_STATE_REGISTERED)
387 new_count = sched_clock() & 0xffffffff;
388 cp->handle = ((u64) i << 32) | new_count;
390 msg_len = (sizeof(struct ds_reg_req) +
391 strlen(cp->service_id));
393 memset(&pbuf, 0, sizeof(pbuf));
394 pbuf.req.tag.type = DS_REG_REQ;
395 pbuf.req.tag.len = (msg_len - sizeof(struct ds_msg_tag));
396 pbuf.req.handle = cp->handle;
399 strcpy(pbuf.req.svc_id, cp->service_id);
401 err = ds_send(lp, &pbuf, msg_len);
403 cp->state = CAP_STATE_REG_SENT;
408 static int ds_handshake(struct ds_info *dp, struct ds_msg_tag *pkt)
411 if (dp->hs_state == DS_HS_START) {
412 if (pkt->type != DS_INIT_ACK)
415 dp->hs_state = DS_HS_DONE;
417 return register_services(dp);
420 if (dp->hs_state != DS_HS_DONE)
423 if (pkt->type == DS_REG_ACK) {
424 struct ds_reg_ack *ap = (struct ds_reg_ack *) pkt;
425 struct ds_cap_state *cp = find_cap(ap->handle);
428 printk(KERN_ERR PFX "REG ACK for unknown handle %lx\n",
432 printk(KERN_INFO PFX "Registered %s service.\n",
434 cp->state = CAP_STATE_REGISTERED;
435 } else if (pkt->type == DS_REG_NACK) {
436 struct ds_reg_nack *np = (struct ds_reg_nack *) pkt;
437 struct ds_cap_state *cp = find_cap(np->handle);
440 printk(KERN_ERR PFX "REG NACK for "
441 "unknown handle %lx\n",
445 printk(KERN_ERR PFX "Could not register %s service\n",
447 cp->state = CAP_STATE_UNKNOWN;
457 static int ds_data(struct ds_info *dp, struct ds_msg_tag *pkt, int len)
459 struct ds_data *dpkt = (struct ds_data *) pkt;
460 struct ds_cap_state *cp = find_cap(dpkt->handle);
463 struct ds_data_nack nack = {
466 .len = (sizeof(struct ds_data_nack) -
467 sizeof(struct ds_msg_tag)),
469 .handle = dpkt->handle,
470 .result = DS_INV_HDL,
473 printk(KERN_ERR PFX "Data for unknown handle %lu\n",
475 ds_send(dp->lp, &nack, sizeof(nack));
477 cp->data(dp->lp, cp, dpkt, len);
482 static void ds_up(struct ds_info *dp)
484 struct ldc_channel *lp = dp->lp;
485 struct ds_ver_req req;
488 req.tag.type = DS_INIT_REQ;
489 req.tag.len = sizeof(req) - sizeof(struct ds_msg_tag);
493 err = ds_send(lp, &req, sizeof(req));
495 dp->hs_state = DS_HS_START;
498 static void ds_event(void *arg, int event)
500 struct ds_info *dp = arg;
501 struct ldc_channel *lp = dp->lp;
505 spin_lock_irqsave(&ds_lock, flags);
507 if (event == LDC_EVENT_UP) {
509 spin_unlock_irqrestore(&ds_lock, flags);
513 if (event != LDC_EVENT_DATA_READY) {
514 printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event);
515 spin_unlock_irqrestore(&ds_lock, flags);
521 struct ds_msg_tag *tag;
523 err = ldc_read(lp, dp->rcv_buf, sizeof(*tag));
525 if (unlikely(err < 0)) {
526 if (err == -ECONNRESET)
534 err = ldc_read(lp, tag + 1, tag->len);
536 if (unlikely(err < 0)) {
537 if (err == -ECONNRESET)
544 if (tag->type < DS_DATA)
545 err = ds_handshake(dp, dp->rcv_buf);
547 err = ds_data(dp, dp->rcv_buf,
549 if (err == -ECONNRESET)
553 spin_unlock_irqrestore(&ds_lock, flags);
556 static int __devinit ds_probe(struct vio_dev *vdev,
557 const struct vio_device_id *id)
559 static int ds_version_printed;
560 struct ldc_channel_config ds_cfg = {
563 .mode = LDC_MODE_STREAM,
565 struct ldc_channel *lp;
569 if (ds_version_printed++ == 0)
570 printk(KERN_INFO "%s", version);
572 dp = kzalloc(sizeof(*dp), GFP_KERNEL);
577 dp->rcv_buf = kzalloc(4096, GFP_KERNEL);
581 dp->rcv_buf_len = 4096;
583 ds_cfg.tx_irq = vdev->tx_irq;
584 ds_cfg.rx_irq = vdev->rx_irq;
586 lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp);
589 goto out_free_rcv_buf;
593 err = ldc_bind(lp, "DS");
614 static int ds_remove(struct vio_dev *vdev)
619 static struct vio_device_id ds_match[] = {
621 .type = "domain-services-port",
626 static struct vio_driver ds_driver = {
627 .id_table = ds_match,
632 .owner = THIS_MODULE,
636 static int __init ds_init(void)
640 for (i = 0; i < ARRAY_SIZE(ds_states); i++)
641 ds_states[i].handle = ((u64)i << 32);
643 return vio_register_driver(&ds_driver);
646 subsys_initcall(ds_init);