[SPARC64]: Abstract out mdesc accesses for better MD update handling.
[linux-2.6.git] / arch / sparc64 / kernel / ds.c
1 /* ds.c: Domain Services driver for Logical Domains
2  *
3  * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
4  */
5
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>
14
15 #include <asm/ldc.h>
16 #include <asm/vio.h>
17 #include <asm/power.h>
18 #include <asm/mdesc.h>
19
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"
24
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);
31
32 struct ds_msg_tag {
33         __u32                   type;
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
43 #define DS_DATA                 0x09
44 #define DS_NACK                 0x0a
45
46         __u32                   len;
47 };
48
49 /* Result codes */
50 #define DS_OK                   0x00
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
55
56 struct ds_version {
57         __u16                   major;
58         __u16                   minor;
59 };
60
61 struct ds_ver_req {
62         struct ds_msg_tag       tag;
63         struct ds_version       ver;
64 };
65
66 struct ds_ver_ack {
67         struct ds_msg_tag       tag;
68         __u16                   minor;
69 };
70
71 struct ds_ver_nack {
72         struct ds_msg_tag       tag;
73         __u16                   major;
74 };
75
76 struct ds_reg_req {
77         struct ds_msg_tag       tag;
78         __u64                   handle;
79         __u16                   major;
80         __u16                   minor;
81         char                    svc_id[0];
82 };
83
84 struct ds_reg_ack {
85         struct ds_msg_tag       tag;
86         __u64                   handle;
87         __u16                   minor;
88 };
89
90 struct ds_reg_nack {
91         struct ds_msg_tag       tag;
92         __u64                   handle;
93         __u16                   major;
94 };
95
96 struct ds_unreg_req {
97         struct ds_msg_tag       tag;
98         __u64                   handle;
99 };
100
101 struct ds_unreg_ack {
102         struct ds_msg_tag       tag;
103         __u64                   handle;
104 };
105
106 struct ds_unreg_nack {
107         struct ds_msg_tag       tag;
108         __u64                   handle;
109 };
110
111 struct ds_data {
112         struct ds_msg_tag       tag;
113         __u64                   handle;
114 };
115
116 struct ds_data_nack {
117         struct ds_msg_tag       tag;
118         __u64                   handle;
119         __u64                   result;
120 };
121
122 struct ds_cap_state {
123         __u64                   handle;
124
125         void                    (*data)(struct ldc_channel *lp,
126                                         struct ds_cap_state *dp,
127                                         void *buf, int len);
128
129         const char              *service_id;
130
131         u8                      state;
132 #define CAP_STATE_UNKNOWN       0x00
133 #define CAP_STATE_REG_SENT      0x01
134 #define CAP_STATE_REGISTERED    0x02
135 };
136
137 static int ds_send(struct ldc_channel *lp, void *data, int len)
138 {
139         int err, limit = 1000;
140
141         err = -EINVAL;
142         while (limit-- > 0) {
143                 err = ldc_write(lp, data, len);
144                 if (!err || (err != -EAGAIN))
145                         break;
146                 udelay(1);
147         }
148
149         return err;
150 }
151
152 struct ds_md_update_req {
153         __u64                           req_num;
154 };
155
156 struct ds_md_update_res {
157         __u64                           req_num;
158         __u32                           result;
159 };
160
161 static void md_update_data(struct ldc_channel *lp,
162                            struct ds_cap_state *dp,
163                            void *buf, int len)
164 {
165         struct ds_data *dpkt = buf;
166         struct ds_md_update_req *rp;
167         struct {
168                 struct ds_data          data;
169                 struct ds_md_update_res res;
170         } pkt;
171
172         rp = (struct ds_md_update_req *) (dpkt + 1);
173
174         printk(KERN_ERR PFX "Machine description update.\n");
175
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;
182
183         ds_send(lp, &pkt, sizeof(pkt));
184
185         mdesc_update();
186 }
187
188 struct ds_shutdown_req {
189         __u64                           req_num;
190         __u32                           ms_delay;
191 };
192
193 struct ds_shutdown_res {
194         __u64                           req_num;
195         __u32                           result;
196         char                            reason[1];
197 };
198
199 static void domain_shutdown_data(struct ldc_channel *lp,
200                                  struct ds_cap_state *dp,
201                                  void *buf, int len)
202 {
203         struct ds_data *dpkt = buf;
204         struct ds_shutdown_req *rp;
205         struct {
206                 struct ds_data          data;
207                 struct ds_shutdown_res  res;
208         } pkt;
209
210         rp = (struct ds_shutdown_req *) (dpkt + 1);
211
212         printk(KERN_ALERT PFX "Shutdown request from "
213                "LDOM manager received.\n");
214
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;
222
223         ds_send(lp, &pkt, sizeof(pkt));
224
225         wake_up_powerd();
226 }
227
228 struct ds_panic_req {
229         __u64                           req_num;
230 };
231
232 struct ds_panic_res {
233         __u64                           req_num;
234         __u32                           result;
235         char                            reason[1];
236 };
237
238 static void domain_panic_data(struct ldc_channel *lp,
239                               struct ds_cap_state *dp,
240                               void *buf, int len)
241 {
242         struct ds_data *dpkt = buf;
243         struct ds_panic_req *rp;
244         struct {
245                 struct ds_data          data;
246                 struct ds_panic_res     res;
247         } pkt;
248
249         rp = (struct ds_panic_req *) (dpkt + 1);
250
251         printk(KERN_ERR PFX "Panic REQ [%lx], len=%d\n",
252                rp->req_num, len);
253
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;
261
262         ds_send(lp, &pkt, sizeof(pkt));
263
264         panic("PANIC requested by LDOM manager.");
265 }
266
267 struct ds_cpu_tag {
268         __u64                           req_num;
269         __u32                           type;
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
274
275 /* Responses */
276 #define DS_CPU_OK                       0x6f
277 #define DS_CPU_ERROR                    0x65
278
279         __u32                           num_records;
280 };
281
282 struct ds_cpu_record {
283         __u32                           cpu_id;
284 };
285
286 static void dr_cpu_data(struct ldc_channel *lp,
287                         struct ds_cap_state *dp,
288                         void *buf, int len)
289 {
290         struct ds_data *dpkt = buf;
291         struct ds_cpu_tag *rp;
292
293         rp = (struct ds_cpu_tag *) (dpkt + 1);
294
295         printk(KERN_ERR PFX "CPU REQ [%lx:%x], len=%d\n",
296                rp->req_num, rp->type, len);
297 }
298
299 struct ds_pri_msg {
300         __u64                           req_num;
301         __u64                           type;
302 #define DS_PRI_REQUEST                  0x00
303 #define DS_PRI_DATA                     0x01
304 #define DS_PRI_UPDATE                   0x02
305 };
306
307 static void ds_pri_data(struct ldc_channel *lp,
308                         struct ds_cap_state *dp,
309                         void *buf, int len)
310 {
311         struct ds_data *dpkt = buf;
312         struct ds_pri_msg *rp;
313
314         rp = (struct ds_pri_msg *) (dpkt + 1);
315
316         printk(KERN_ERR PFX "PRI REQ [%lx:%lx], len=%d\n",
317                rp->req_num, rp->type, len);
318 }
319
320 struct ds_cap_state ds_states[] = {
321         {
322                 .service_id     = "md-update",
323                 .data           = md_update_data,
324         },
325         {
326                 .service_id     = "domain-shutdown",
327                 .data           = domain_shutdown_data,
328         },
329         {
330                 .service_id     = "domain-panic",
331                 .data           = domain_panic_data,
332         },
333         {
334                 .service_id     = "dr-cpu",
335                 .data           = dr_cpu_data,
336         },
337         {
338                 .service_id     = "pri",
339                 .data           = ds_pri_data,
340         },
341 };
342
343 static struct ds_cap_state *find_cap(u64 handle)
344 {
345         unsigned int index = handle >> 32;
346
347         if (index >= ARRAY_SIZE(ds_states))
348                 return NULL;
349         return &ds_states[index];
350 }
351
352 static DEFINE_SPINLOCK(ds_lock);
353
354 struct ds_info {
355         struct ldc_channel      *lp;
356         u8                      hs_state;
357 #define DS_HS_START             0x01
358 #define DS_HS_DONE              0x02
359
360         void                    *rcv_buf;
361         int                     rcv_buf_len;
362 };
363
364 static void ds_conn_reset(struct ds_info *dp)
365 {
366         printk(KERN_ERR PFX "ds_conn_reset() from %p\n",
367                __builtin_return_address(0));
368 }
369
370 static int register_services(struct ds_info *dp)
371 {
372         struct ldc_channel *lp = dp->lp;
373         int i;
374
375         for (i = 0; i < ARRAY_SIZE(ds_states); i++) {
376                 struct {
377                         struct ds_reg_req req;
378                         u8 id_buf[256];
379                 } pbuf;
380                 struct ds_cap_state *cp = &ds_states[i];
381                 int err, msg_len;
382                 u64 new_count;
383
384                 if (cp->state == CAP_STATE_REGISTERED)
385                         continue;
386
387                 new_count = sched_clock() & 0xffffffff;
388                 cp->handle = ((u64) i << 32) | new_count;
389
390                 msg_len = (sizeof(struct ds_reg_req) +
391                            strlen(cp->service_id));
392
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;
397                 pbuf.req.major = 1;
398                 pbuf.req.minor = 0;
399                 strcpy(pbuf.req.svc_id, cp->service_id);
400
401                 err = ds_send(lp, &pbuf, msg_len);
402                 if (err > 0)
403                         cp->state = CAP_STATE_REG_SENT;
404         }
405         return 0;
406 }
407
408 static int ds_handshake(struct ds_info *dp, struct ds_msg_tag *pkt)
409 {
410
411         if (dp->hs_state == DS_HS_START) {
412                 if (pkt->type != DS_INIT_ACK)
413                         goto conn_reset;
414
415                 dp->hs_state = DS_HS_DONE;
416
417                 return register_services(dp);
418         }
419
420         if (dp->hs_state != DS_HS_DONE)
421                 goto conn_reset;
422
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);
426
427                 if (!cp) {
428                         printk(KERN_ERR PFX "REG ACK for unknown handle %lx\n",
429                                ap->handle);
430                         return 0;
431                 }
432                 printk(KERN_INFO PFX "Registered %s service.\n",
433                        cp->service_id);
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);
438
439                 if (!cp) {
440                         printk(KERN_ERR PFX "REG NACK for "
441                                "unknown handle %lx\n",
442                                np->handle);
443                         return 0;
444                 }
445                 printk(KERN_ERR PFX "Could not register %s service\n",
446                        cp->service_id);
447                 cp->state = CAP_STATE_UNKNOWN;
448         }
449
450         return 0;
451
452 conn_reset:
453         ds_conn_reset(dp);
454         return -ECONNRESET;
455 }
456
457 static int ds_data(struct ds_info *dp, struct ds_msg_tag *pkt, int len)
458 {
459         struct ds_data *dpkt = (struct ds_data *) pkt;
460         struct ds_cap_state *cp = find_cap(dpkt->handle);
461
462         if (!cp) {
463                 struct ds_data_nack nack = {
464                         .tag = {
465                                 .type = DS_NACK,
466                                 .len = (sizeof(struct ds_data_nack) -
467                                         sizeof(struct ds_msg_tag)),
468                         },
469                         .handle = dpkt->handle,
470                         .result = DS_INV_HDL,
471                 };
472
473                 printk(KERN_ERR PFX "Data for unknown handle %lu\n",
474                        dpkt->handle);
475                 ds_send(dp->lp, &nack, sizeof(nack));
476         } else {
477                 cp->data(dp->lp, cp, dpkt, len);
478         }
479         return 0;
480 }
481
482 static void ds_up(struct ds_info *dp)
483 {
484         struct ldc_channel *lp = dp->lp;
485         struct ds_ver_req req;
486         int err;
487
488         req.tag.type = DS_INIT_REQ;
489         req.tag.len = sizeof(req) - sizeof(struct ds_msg_tag);
490         req.ver.major = 1;
491         req.ver.minor = 0;
492
493         err = ds_send(lp, &req, sizeof(req));
494         if (err > 0)
495                 dp->hs_state = DS_HS_START;
496 }
497
498 static void ds_event(void *arg, int event)
499 {
500         struct ds_info *dp = arg;
501         struct ldc_channel *lp = dp->lp;
502         unsigned long flags;
503         int err;
504
505         spin_lock_irqsave(&ds_lock, flags);
506
507         if (event == LDC_EVENT_UP) {
508                 ds_up(dp);
509                 spin_unlock_irqrestore(&ds_lock, flags);
510                 return;
511         }
512
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);
516                 return;
517         }
518
519         err = 0;
520         while (1) {
521                 struct ds_msg_tag *tag;
522
523                 err = ldc_read(lp, dp->rcv_buf, sizeof(*tag));
524
525                 if (unlikely(err < 0)) {
526                         if (err == -ECONNRESET)
527                                 ds_conn_reset(dp);
528                         break;
529                 }
530                 if (err == 0)
531                         break;
532
533                 tag = dp->rcv_buf;
534                 err = ldc_read(lp, tag + 1, tag->len);
535
536                 if (unlikely(err < 0)) {
537                         if (err == -ECONNRESET)
538                                 ds_conn_reset(dp);
539                         break;
540                 }
541                 if (err < tag->len)
542                         break;
543
544                 if (tag->type < DS_DATA)
545                         err = ds_handshake(dp, dp->rcv_buf);
546                 else
547                         err = ds_data(dp, dp->rcv_buf,
548                                       sizeof(*tag) + err);
549                 if (err == -ECONNRESET)
550                         break;
551         }
552
553         spin_unlock_irqrestore(&ds_lock, flags);
554 }
555
556 static int __devinit ds_probe(struct vio_dev *vdev,
557                               const struct vio_device_id *id)
558 {
559         static int ds_version_printed;
560         struct ldc_channel_config ds_cfg = {
561                 .event          = ds_event,
562                 .mtu            = 4096,
563                 .mode           = LDC_MODE_STREAM,
564         };
565         struct ldc_channel *lp;
566         struct ds_info *dp;
567         int err;
568
569         if (ds_version_printed++ == 0)
570                 printk(KERN_INFO "%s", version);
571
572         dp = kzalloc(sizeof(*dp), GFP_KERNEL);
573         err = -ENOMEM;
574         if (!dp)
575                 goto out_err;
576
577         dp->rcv_buf = kzalloc(4096, GFP_KERNEL);
578         if (!dp->rcv_buf)
579                 goto out_free_dp;
580
581         dp->rcv_buf_len = 4096;
582
583         ds_cfg.tx_irq = vdev->tx_irq;
584         ds_cfg.rx_irq = vdev->rx_irq;
585
586         lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp);
587         if (IS_ERR(lp)) {
588                 err = PTR_ERR(lp);
589                 goto out_free_rcv_buf;
590         }
591         dp->lp = lp;
592
593         err = ldc_bind(lp, "DS");
594         if (err)
595                 goto out_free_ldc;
596
597         start_powerd();
598
599         return err;
600
601 out_free_ldc:
602         ldc_free(dp->lp);
603
604 out_free_rcv_buf:
605         kfree(dp->rcv_buf);
606
607 out_free_dp:
608         kfree(dp);
609
610 out_err:
611         return err;
612 }
613
614 static int ds_remove(struct vio_dev *vdev)
615 {
616         return 0;
617 }
618
619 static struct vio_device_id ds_match[] = {
620         {
621                 .type = "domain-services-port",
622         },
623         {},
624 };
625
626 static struct vio_driver ds_driver = {
627         .id_table       = ds_match,
628         .probe          = ds_probe,
629         .remove         = ds_remove,
630         .driver         = {
631                 .name   = "ds",
632                 .owner  = THIS_MODULE,
633         }
634 };
635
636 static int __init ds_init(void)
637 {
638         int i;
639
640         for (i = 0; i < ARRAY_SIZE(ds_states); i++)
641                 ds_states[i].handle = ((u64)i << 32);
642
643         return vio_register_driver(&ds_driver);
644 }
645
646 subsys_initcall(ds_init);