ds.c 25.4 KB
Newer Older
1
2
/* ds.c: Domain Services driver for Logical Domains
 *
3
 * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
4
5
6
7
8
9
10
11
12
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/delay.h>
13
#include <linux/mutex.h>
14
#include <linux/kthread.h>
15
#include <linux/reboot.h>
16
#include <linux/cpu.h>
17

18
#include <asm/hypervisor.h>
19
20
#include <asm/ldc.h>
#include <asm/vio.h>
21
#include <asm/mdesc.h>
22
#include <asm/head.h>
23
#include <asm/irq.h>
24

25
26
#include "kernel.h"

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#define DRV_MODULE_NAME		"ds"
#define PFX DRV_MODULE_NAME	": "
#define DRV_MODULE_VERSION	"1.0"
#define DRV_MODULE_RELDATE	"Jul 11, 2007"

static char version[] __devinitdata =
	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
MODULE_DESCRIPTION("Sun LDOM domain services driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);

struct ds_msg_tag {
	__u32			type;
#define DS_INIT_REQ		0x00
#define DS_INIT_ACK		0x01
#define DS_INIT_NACK		0x02
#define DS_REG_REQ		0x03
#define DS_REG_ACK		0x04
#define DS_REG_NACK		0x05
#define DS_UNREG_REQ		0x06
#define DS_UNREG_ACK		0x07
#define DS_UNREG_NACK		0x08
#define DS_DATA			0x09
#define DS_NACK			0x0a

	__u32			len;
};

/* Result codes */
#define DS_OK			0x00
#define DS_REG_VER_NACK		0x01
#define DS_REG_DUP		0x02
#define DS_INV_HDL		0x03
#define DS_TYPE_UNKNOWN		0x04

struct ds_version {
	__u16			major;
	__u16			minor;
};

struct ds_ver_req {
	struct ds_msg_tag	tag;
	struct ds_version	ver;
};

struct ds_ver_ack {
	struct ds_msg_tag	tag;
	__u16			minor;
};

struct ds_ver_nack {
	struct ds_msg_tag	tag;
	__u16			major;
};

struct ds_reg_req {
	struct ds_msg_tag	tag;
	__u64			handle;
	__u16			major;
	__u16			minor;
	char			svc_id[0];
};

struct ds_reg_ack {
	struct ds_msg_tag	tag;
	__u64			handle;
	__u16			minor;
};

struct ds_reg_nack {
	struct ds_msg_tag	tag;
	__u64			handle;
	__u16			major;
};

struct ds_unreg_req {
	struct ds_msg_tag	tag;
	__u64			handle;
};

struct ds_unreg_ack {
	struct ds_msg_tag	tag;
	__u64			handle;
};

struct ds_unreg_nack {
	struct ds_msg_tag	tag;
	__u64			handle;
};

struct ds_data {
	struct ds_msg_tag	tag;
	__u64			handle;
};

struct ds_data_nack {
	struct ds_msg_tag	tag;
	__u64			handle;
	__u64			result;
};

129
struct ds_info;
130
131
132
struct ds_cap_state {
	__u64			handle;

133
	void			(*data)(struct ds_info *dp,
134
					struct ds_cap_state *cp,
135
136
137
138
139
140
141
142
143
144
					void *buf, int len);

	const char		*service_id;

	u8			state;
#define CAP_STATE_UNKNOWN	0x00
#define CAP_STATE_REG_SENT	0x01
#define CAP_STATE_REGISTERED	0x02
};

145
static void md_update_data(struct ds_info *dp, struct ds_cap_state *cp,
146
			   void *buf, int len);
147
static void domain_shutdown_data(struct ds_info *dp,
148
149
				 struct ds_cap_state *cp,
				 void *buf, int len);
150
static void domain_panic_data(struct ds_info *dp,
151
152
			      struct ds_cap_state *cp,
			      void *buf, int len);
153
#ifdef CONFIG_HOTPLUG_CPU
154
static void dr_cpu_data(struct ds_info *dp,
155
156
			struct ds_cap_state *cp,
			void *buf, int len);
157
#endif
158
static void ds_pri_data(struct ds_info *dp,
159
160
			struct ds_cap_state *cp,
			void *buf, int len);
161
static void ds_var_data(struct ds_info *dp,
162
163
164
			struct ds_cap_state *cp,
			void *buf, int len);

165
static struct ds_cap_state ds_states_template[] = {
166
167
168
169
170
171
172
173
174
175
176
177
	{
		.service_id	= "md-update",
		.data		= md_update_data,
	},
	{
		.service_id	= "domain-shutdown",
		.data		= domain_shutdown_data,
	},
	{
		.service_id	= "domain-panic",
		.data		= domain_panic_data,
	},
178
#ifdef CONFIG_HOTPLUG_CPU
179
180
181
182
	{
		.service_id	= "dr-cpu",
		.data		= dr_cpu_data,
	},
183
#endif
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
	{
		.service_id	= "pri",
		.data		= ds_pri_data,
	},
	{
		.service_id	= "var-config",
		.data		= ds_var_data,
	},
	{
		.service_id	= "var-config-backup",
		.data		= ds_var_data,
	},
};

static DEFINE_SPINLOCK(ds_lock);

struct ds_info {
	struct ldc_channel	*lp;
	u8			hs_state;
#define DS_HS_START		0x01
#define DS_HS_DONE		0x02

206
207
	u64			id;

208
209
	void			*rcv_buf;
	int			rcv_buf_len;
210
211
212
213
214

	struct ds_cap_state	*ds_states;
	int			num_ds_states;

	struct ds_info		*next;
215
216
};

217
static struct ds_info *ds_info_list;
218

219
static struct ds_cap_state *find_cap(struct ds_info *dp, u64 handle)
220
221
222
{
	unsigned int index = handle >> 32;

223
	if (index >= dp->num_ds_states)
224
		return NULL;
225
	return &dp->ds_states[index];
226
227
}

228
229
static struct ds_cap_state *find_cap_by_string(struct ds_info *dp,
					       const char *name)
230
231
232
{
	int i;

233
234
	for (i = 0; i < dp->num_ds_states; i++) {
		if (strcmp(dp->ds_states[i].service_id, name))
235
236
			continue;

237
		return &dp->ds_states[i];
238
239
240
241
	}
	return NULL;
}

242
static int __ds_send(struct ldc_channel *lp, void *data, int len)
243
244
245
246
247
248
249
250
251
252
253
254
255
256
{
	int err, limit = 1000;

	err = -EINVAL;
	while (limit-- > 0) {
		err = ldc_write(lp, data, len);
		if (!err || (err != -EAGAIN))
			break;
		udelay(1);
	}

	return err;
}

257
258
259
260
261
262
263
264
265
266
267
268
static int ds_send(struct ldc_channel *lp, void *data, int len)
{
	unsigned long flags;
	int err;

	spin_lock_irqsave(&ds_lock, flags);
	err = __ds_send(lp, data, len);
	spin_unlock_irqrestore(&ds_lock, flags);

	return err;
}

269
270
271
272
273
274
275
276
277
struct ds_md_update_req {
	__u64				req_num;
};

struct ds_md_update_res {
	__u64				req_num;
	__u32				result;
};

278
279
static void md_update_data(struct ds_info *dp,
			   struct ds_cap_state *cp,
280
281
			   void *buf, int len)
{
282
	struct ldc_channel *lp = dp->lp;
283
284
285
286
287
288
289
290
291
	struct ds_data *dpkt = buf;
	struct ds_md_update_req *rp;
	struct {
		struct ds_data		data;
		struct ds_md_update_res	res;
	} pkt;

	rp = (struct ds_md_update_req *) (dpkt + 1);

292
	printk(KERN_INFO "ds-%llu: Machine description update.\n", dp->id);
293

294
295
	mdesc_update();

296
297
298
	memset(&pkt, 0, sizeof(pkt));
	pkt.data.tag.type = DS_DATA;
	pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
299
	pkt.data.handle = cp->handle;
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
	pkt.res.req_num = rp->req_num;
	pkt.res.result = DS_OK;

	ds_send(lp, &pkt, sizeof(pkt));
}

struct ds_shutdown_req {
	__u64				req_num;
	__u32				ms_delay;
};

struct ds_shutdown_res {
	__u64				req_num;
	__u32				result;
	char				reason[1];
};

317
318
static void domain_shutdown_data(struct ds_info *dp,
				 struct ds_cap_state *cp,
319
320
				 void *buf, int len)
{
321
	struct ldc_channel *lp = dp->lp;
322
323
324
325
326
327
328
329
330
	struct ds_data *dpkt = buf;
	struct ds_shutdown_req *rp;
	struct {
		struct ds_data		data;
		struct ds_shutdown_res	res;
	} pkt;

	rp = (struct ds_shutdown_req *) (dpkt + 1);

331
	printk(KERN_ALERT "ds-%llu: Shutdown request from "
332
	       "LDOM manager received.\n", dp->id);
333
334
335
336

	memset(&pkt, 0, sizeof(pkt));
	pkt.data.tag.type = DS_DATA;
	pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
337
	pkt.data.handle = cp->handle;
338
339
340
341
342
343
	pkt.res.req_num = rp->req_num;
	pkt.res.result = DS_OK;
	pkt.res.reason[0] = 0;

	ds_send(lp, &pkt, sizeof(pkt));

344
	orderly_poweroff(true);
345
346
347
348
349
350
351
352
353
354
355
356
}

struct ds_panic_req {
	__u64				req_num;
};

struct ds_panic_res {
	__u64				req_num;
	__u32				result;
	char				reason[1];
};

357
358
static void domain_panic_data(struct ds_info *dp,
			      struct ds_cap_state *cp,
359
360
			      void *buf, int len)
{
361
	struct ldc_channel *lp = dp->lp;
362
363
364
365
366
367
368
369
370
	struct ds_data *dpkt = buf;
	struct ds_panic_req *rp;
	struct {
		struct ds_data		data;
		struct ds_panic_res	res;
	} pkt;

	rp = (struct ds_panic_req *) (dpkt + 1);

371
	printk(KERN_ALERT "ds-%llu: Panic request from "
372
	       "LDOM manager received.\n", dp->id);
373
374
375
376

	memset(&pkt, 0, sizeof(pkt));
	pkt.data.tag.type = DS_DATA;
	pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
377
	pkt.data.handle = cp->handle;
378
379
380
381
382
383
384
385
386
	pkt.res.req_num = rp->req_num;
	pkt.res.result = DS_OK;
	pkt.res.reason[0] = 0;

	ds_send(lp, &pkt, sizeof(pkt));

	panic("PANIC requested by LDOM manager.");
}

387
#ifdef CONFIG_HOTPLUG_CPU
388
struct dr_cpu_tag {
389
390
	__u64				req_num;
	__u32				type;
391
392
393
394
#define DR_CPU_CONFIGURE		0x43
#define DR_CPU_UNCONFIGURE		0x55
#define DR_CPU_FORCE_UNCONFIGURE	0x46
#define DR_CPU_STATUS			0x53
395
396

/* Responses */
397
398
#define DR_CPU_OK			0x6f
#define DR_CPU_ERROR			0x65
399
400
401
402

	__u32				num_records;
};

403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
struct dr_cpu_resp_entry {
	__u32				cpu;
	__u32				result;
#define DR_CPU_RES_OK			0x00
#define DR_CPU_RES_FAILURE		0x01
#define DR_CPU_RES_BLOCKED		0x02
#define DR_CPU_RES_CPU_NOT_RESPONDING	0x03
#define DR_CPU_RES_NOT_IN_MD		0x04

	__u32				stat;
#define DR_CPU_STAT_NOT_PRESENT		0x00
#define DR_CPU_STAT_UNCONFIGURED	0x01
#define DR_CPU_STAT_CONFIGURED		0x02

	__u32				str_off;
418
419
};

420
421
422
static void __dr_cpu_send_error(struct ds_info *dp,
				struct ds_cap_state *cp,
				struct ds_data *data)
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
{
	struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1);
	struct {
		struct ds_data		data;
		struct dr_cpu_tag	tag;
	} pkt;
	int msg_len;

	memset(&pkt, 0, sizeof(pkt));
	pkt.data.tag.type = DS_DATA;
	pkt.data.handle = cp->handle;
	pkt.tag.req_num = tag->req_num;
	pkt.tag.type = DR_CPU_ERROR;
	pkt.tag.num_records = 0;

	msg_len = (sizeof(struct ds_data) +
		   sizeof(struct dr_cpu_tag));

	pkt.data.tag.len = msg_len - sizeof(struct ds_msg_tag);

443
	__ds_send(dp->lp, &pkt, msg_len);
444
445
}

446
447
448
static void dr_cpu_send_error(struct ds_info *dp,
			      struct ds_cap_state *cp,
			      struct ds_data *data)
449
450
451
452
{
	unsigned long flags;

	spin_lock_irqsave(&ds_lock, flags);
453
	__dr_cpu_send_error(dp, cp, data);
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
	spin_unlock_irqrestore(&ds_lock, flags);
}

#define CPU_SENTINEL	0xffffffff

static void purge_dups(u32 *list, u32 num_ents)
{
	unsigned int i;

	for (i = 0; i < num_ents; i++) {
		u32 cpu = list[i];
		unsigned int j;

		if (cpu == CPU_SENTINEL)
			continue;

		for (j = i + 1; j < num_ents; j++) {
			if (list[j] == cpu)
				list[j] = CPU_SENTINEL;
		}
	}
}

static int dr_cpu_size_response(int ncpus)
{
	return (sizeof(struct ds_data) +
		sizeof(struct dr_cpu_tag) +
		(sizeof(struct dr_cpu_resp_entry) * ncpus));
}

static void dr_cpu_init_response(struct ds_data *resp, u64 req_num,
				 u64 handle, int resp_len, int ncpus,
				 cpumask_t *mask, u32 default_stat)
{
	struct dr_cpu_resp_entry *ent;
	struct dr_cpu_tag *tag;
	int i, cpu;

	tag = (struct dr_cpu_tag *) (resp + 1);
	ent = (struct dr_cpu_resp_entry *) (tag + 1);

	resp->tag.type = DS_DATA;
	resp->tag.len = resp_len - sizeof(struct ds_msg_tag);
	resp->handle = handle;
	tag->req_num = req_num;
	tag->type = DR_CPU_OK;
	tag->num_records = ncpus;

	i = 0;
503
	for_each_cpu(cpu, mask) {
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
		ent[i].cpu = cpu;
		ent[i].result = DR_CPU_RES_OK;
		ent[i].stat = default_stat;
		i++;
	}
	BUG_ON(i != ncpus);
}

static void dr_cpu_mark(struct ds_data *resp, int cpu, int ncpus,
			u32 res, u32 stat)
{
	struct dr_cpu_resp_entry *ent;
	struct dr_cpu_tag *tag;
	int i;

	tag = (struct dr_cpu_tag *) (resp + 1);
	ent = (struct dr_cpu_resp_entry *) (tag + 1);

	for (i = 0; i < ncpus; i++) {
		if (ent[i].cpu != cpu)
			continue;
		ent[i].result = res;
		ent[i].stat = stat;
		break;
	}
}

531
532
533
534
static int __cpuinit dr_cpu_configure(struct ds_info *dp,
				      struct ds_cap_state *cp,
				      u64 req_num,
				      cpumask_t *mask)
535
536
537
538
539
{
	struct ds_data *resp;
	int resp_len, ncpus, cpu;
	unsigned long flags;

540
	ncpus = cpumask_weight(mask);
541
542
543
544
545
546
547
548
549
	resp_len = dr_cpu_size_response(ncpus);
	resp = kzalloc(resp_len, GFP_KERNEL);
	if (!resp)
		return -ENOMEM;

	dr_cpu_init_response(resp, req_num, cp->handle,
			     resp_len, ncpus, mask,
			     DR_CPU_STAT_CONFIGURED);

550
	mdesc_populate_present_mask(mask);
551
	mdesc_fill_in_cpu_data(mask);
552

553
	for_each_cpu(cpu, mask) {
554
555
		int err;

556
		printk(KERN_INFO "ds-%llu: Starting cpu %d...\n",
557
		       dp->id, cpu);
558
		err = cpu_up(cpu);
559
		if (err) {
560
561
562
563
564
565
566
567
568
569
570
571
			__u32 res = DR_CPU_RES_FAILURE;
			__u32 stat = DR_CPU_STAT_UNCONFIGURED;

			if (!cpu_present(cpu)) {
				/* CPU not present in MD */
				res = DR_CPU_RES_NOT_IN_MD;
				stat = DR_CPU_STAT_NOT_PRESENT;
			} else if (err == -ENODEV) {
				/* CPU did not call in successfully */
				res = DR_CPU_RES_CPU_NOT_RESPONDING;
			}

572
			printk(KERN_INFO "ds-%llu: CPU startup failed err=%d\n",
573
			       dp->id, err);
574
			dr_cpu_mark(resp, cpu, ncpus, res, stat);
575
		}
576
577
578
	}

	spin_lock_irqsave(&ds_lock, flags);
579
	__ds_send(dp->lp, resp, resp_len);
580
581
582
583
	spin_unlock_irqrestore(&ds_lock, flags);

	kfree(resp);

584
585
586
	/* Redistribute IRQs, taking into account the new cpus.  */
	fixup_irqs();

587
588
589
	return 0;
}

590
591
592
static int dr_cpu_unconfigure(struct ds_info *dp,
			      struct ds_cap_state *cp,
			      u64 req_num,
593
594
595
			      cpumask_t *mask)
{
	struct ds_data *resp;
596
597
	int resp_len, ncpus, cpu;
	unsigned long flags;
598

599
	ncpus = cpumask_weight(mask);
600
601
602
603
604
605
606
607
608
	resp_len = dr_cpu_size_response(ncpus);
	resp = kzalloc(resp_len, GFP_KERNEL);
	if (!resp)
		return -ENOMEM;

	dr_cpu_init_response(resp, req_num, cp->handle,
			     resp_len, ncpus, mask,
			     DR_CPU_STAT_UNCONFIGURED);

609
	for_each_cpu(cpu, mask) {
610
611
		int err;

612
		printk(KERN_INFO "ds-%llu: Shutting down cpu %d...\n",
613
		       dp->id, cpu);
614
615
616
617
618
619
620
621
		err = cpu_down(cpu);
		if (err)
			dr_cpu_mark(resp, cpu, ncpus,
				    DR_CPU_RES_FAILURE,
				    DR_CPU_STAT_CONFIGURED);
	}

	spin_lock_irqsave(&ds_lock, flags);
622
	__ds_send(dp->lp, resp, resp_len);
623
624
	spin_unlock_irqrestore(&ds_lock, flags);

625
626
	kfree(resp);

627
	return 0;
628
629
}

630
631
632
static void __cpuinit dr_cpu_data(struct ds_info *dp,
				  struct ds_cap_state *cp,
				  void *buf, int len)
633
{
634
635
636
637
	struct ds_data *data = buf;
	struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1);
	u32 *cpu_list = (u32 *) (tag + 1);
	u64 req_num = tag->req_num;
638
	cpumask_t mask;
639
640
	unsigned int i;
	int err;
641

642
643
644
645
646
	switch (tag->type) {
	case DR_CPU_CONFIGURE:
	case DR_CPU_UNCONFIGURE:
	case DR_CPU_FORCE_UNCONFIGURE:
		break;
647

648
	default:
649
		dr_cpu_send_error(dp, cp, data);
650
		return;
651
652
	}

653
	purge_dups(cpu_list, tag->num_records);
654

655
	cpumask_clear(&mask);
656
657
658
	for (i = 0; i < tag->num_records; i++) {
		if (cpu_list[i] == CPU_SENTINEL)
			continue;
659

660
		if (cpu_list[i] < nr_cpu_ids)
661
			cpumask_set_cpu(cpu_list[i], &mask);
662
663
	}

664
	if (tag->type == DR_CPU_CONFIGURE)
665
		err = dr_cpu_configure(dp, cp, req_num, &mask);
666
	else
667
		err = dr_cpu_unconfigure(dp, cp, req_num, &mask);
668

669
	if (err)
670
		dr_cpu_send_error(dp, cp, data);
671
}
672
#endif /* CONFIG_HOTPLUG_CPU */
673
674
675
676
677
678
679
680
681

struct ds_pri_msg {
	__u64				req_num;
	__u64				type;
#define DS_PRI_REQUEST			0x00
#define DS_PRI_DATA			0x01
#define DS_PRI_UPDATE			0x02
};

682
683
static void ds_pri_data(struct ds_info *dp,
			struct ds_cap_state *cp,
684
685
686
687
688
689
690
			void *buf, int len)
{
	struct ds_data *dpkt = buf;
	struct ds_pri_msg *rp;

	rp = (struct ds_pri_msg *) (dpkt + 1);

691
	printk(KERN_INFO "ds-%llu: PRI REQ [%llx:%llx], len=%d\n",
692
	       dp->id, rp->req_num, rp->type, len);
693
694
}

695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
struct ds_var_hdr {
	__u32				type;
#define DS_VAR_SET_REQ			0x00
#define DS_VAR_DELETE_REQ		0x01
#define DS_VAR_SET_RESP			0x02
#define DS_VAR_DELETE_RESP		0x03
};

struct ds_var_set_msg {
	struct ds_var_hdr		hdr;
	char				name_and_value[0];
};

struct ds_var_delete_msg {
	struct ds_var_hdr		hdr;
	char				name[0];
};

struct ds_var_resp {
	struct ds_var_hdr		hdr;
	__u32				result;
#define DS_VAR_SUCCESS			0x00
#define DS_VAR_NO_SPACE			0x01
#define DS_VAR_INVALID_VAR		0x02
#define DS_VAR_INVALID_VAL		0x03
#define DS_VAR_NOT_PRESENT		0x04
};

static DEFINE_MUTEX(ds_var_mutex);
static int ds_var_doorbell;
static int ds_var_response;

727
728
static void ds_var_data(struct ds_info *dp,
			struct ds_cap_state *cp,
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
			void *buf, int len)
{
	struct ds_data *dpkt = buf;
	struct ds_var_resp *rp;

	rp = (struct ds_var_resp *) (dpkt + 1);

	if (rp->hdr.type != DS_VAR_SET_RESP &&
	    rp->hdr.type != DS_VAR_DELETE_RESP)
		return;

	ds_var_response = rp->result;
	wmb();
	ds_var_doorbell = 1;
}

void ldom_set_var(const char *var, const char *value)
{
	struct ds_cap_state *cp;
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
	struct ds_info *dp;
	unsigned long flags;

	spin_lock_irqsave(&ds_lock, flags);
	cp = NULL;
	for (dp = ds_info_list; dp; dp = dp->next) {
		struct ds_cap_state *tmp;

		tmp = find_cap_by_string(dp, "var-config");
		if (tmp && tmp->state == CAP_STATE_REGISTERED) {
			cp = tmp;
			break;
		}
	}
	if (!cp) {
		for (dp = ds_info_list; dp; dp = dp->next) {
			struct ds_cap_state *tmp;
765

766
767
768
769
770
771
772
773
			tmp = find_cap_by_string(dp, "var-config-backup");
			if (tmp && tmp->state == CAP_STATE_REGISTERED) {
				cp = tmp;
				break;
			}
		}
	}
	spin_unlock_irqrestore(&ds_lock, flags);
774

775
	if (cp) {
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
		union {
			struct {
				struct ds_data		data;
				struct ds_var_set_msg	msg;
			} header;
			char			all[512];
		} pkt;
		char  *base, *p;
		int msg_len, loops;

		memset(&pkt, 0, sizeof(pkt));
		pkt.header.data.tag.type = DS_DATA;
		pkt.header.data.handle = cp->handle;
		pkt.header.msg.hdr.type = DS_VAR_SET_REQ;
		base = p = &pkt.header.msg.name_and_value[0];
		strcpy(p, var);
		p += strlen(var) + 1;
		strcpy(p, value);
		p += strlen(value) + 1;

		msg_len = (sizeof(struct ds_data) +
797
798
			   sizeof(struct ds_var_set_msg) +
			   (p - base));
799
800
801
802
803
804
805
806
807
		msg_len = (msg_len + 3) & ~3;
		pkt.header.data.tag.len = msg_len - sizeof(struct ds_msg_tag);

		mutex_lock(&ds_var_mutex);

		spin_lock_irqsave(&ds_lock, flags);
		ds_var_doorbell = 0;
		ds_var_response = -1;

808
		__ds_send(dp->lp, &pkt, msg_len);
809
810
811
812
813
814
815
816
817
818
819
820
821
822
		spin_unlock_irqrestore(&ds_lock, flags);

		loops = 1000;
		while (ds_var_doorbell == 0) {
			if (loops-- < 0)
				break;
			barrier();
			udelay(100);
		}

		mutex_unlock(&ds_var_mutex);

		if (ds_var_doorbell == 0 ||
		    ds_var_response != DS_VAR_SUCCESS)
823
			printk(KERN_ERR "ds-%llu: var-config [%s:%s] "
824
			       "failed, response(%d).\n",
825
			       dp->id, var, value,
826
827
828
829
830
831
832
833
			       ds_var_response);
	} else {
		printk(KERN_ERR PFX "var-config not registered so "
		       "could not set (%s) variable to (%s).\n",
		       var, value);
	}
}

834
835
836
static char full_boot_str[256] __attribute__((aligned(32)));
static int reboot_data_supported;

837
838
839
840
841
842
void ldom_reboot(const char *boot_command)
{
	/* Don't bother with any of this if the boot_command
	 * is empty.
	 */
	if (boot_command && strlen(boot_command)) {
843
		unsigned long len;
844
845
846

		strcpy(full_boot_str, "boot ");
		strcpy(full_boot_str + strlen("boot "), boot_command);
847
		len = strlen(full_boot_str);
848

849
850
851
852
853
854
855
856
857
858
859
		if (reboot_data_supported) {
			unsigned long ra = kimage_addr_to_ra(full_boot_str);
			unsigned long hv_ret;

			hv_ret = sun4v_reboot_data_set(ra, len);
			if (hv_ret != HV_EOK)
				pr_err("SUN4V: Unable to set reboot data "
				       "hv_ret=%lu\n", hv_ret);
		} else {
			ldom_set_var("reboot-command", full_boot_str);
		}
860
861
862
863
	}
	sun4v_mach_sir();
}

864
865
866
867
868
void ldom_power_off(void)
{
	sun4v_mach_exit(0);
}

869
870
static void ds_conn_reset(struct ds_info *dp)
{
871
	printk(KERN_ERR "ds-%llu: ds_conn_reset() from %p\n",
872
	       dp->id, __builtin_return_address(0));
873
874
875
876
877
878
879
}

static int register_services(struct ds_info *dp)
{
	struct ldc_channel *lp = dp->lp;
	int i;

880
	for (i = 0; i < dp->num_ds_states; i++) {
881
882
883
884
		struct {
			struct ds_reg_req req;
			u8 id_buf[256];
		} pbuf;
885
		struct ds_cap_state *cp = &dp->ds_states[i];
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
		int err, msg_len;
		u64 new_count;

		if (cp->state == CAP_STATE_REGISTERED)
			continue;

		new_count = sched_clock() & 0xffffffff;
		cp->handle = ((u64) i << 32) | new_count;

		msg_len = (sizeof(struct ds_reg_req) +
			   strlen(cp->service_id));

		memset(&pbuf, 0, sizeof(pbuf));
		pbuf.req.tag.type = DS_REG_REQ;
		pbuf.req.tag.len = (msg_len - sizeof(struct ds_msg_tag));
		pbuf.req.handle = cp->handle;
		pbuf.req.major = 1;
		pbuf.req.minor = 0;
		strcpy(pbuf.req.svc_id, cp->service_id);

906
		err = __ds_send(lp, &pbuf, msg_len);
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
		if (err > 0)
			cp->state = CAP_STATE_REG_SENT;
	}
	return 0;
}

static int ds_handshake(struct ds_info *dp, struct ds_msg_tag *pkt)
{

	if (dp->hs_state == DS_HS_START) {
		if (pkt->type != DS_INIT_ACK)
			goto conn_reset;

		dp->hs_state = DS_HS_DONE;

		return register_services(dp);
	}

	if (dp->hs_state != DS_HS_DONE)
		goto conn_reset;

	if (pkt->type == DS_REG_ACK) {
		struct ds_reg_ack *ap = (struct ds_reg_ack *) pkt;
930
		struct ds_cap_state *cp = find_cap(dp, ap->handle);
931
932

		if (!cp) {
933
934
			printk(KERN_ERR "ds-%llu: REG ACK for unknown "
			       "handle %llx\n", dp->id, ap->handle);
935
936
			return 0;
		}
937
		printk(KERN_INFO "ds-%llu: Registered %s service.\n",
938
		       dp->id, cp->service_id);
939
940
941
		cp->state = CAP_STATE_REGISTERED;
	} else if (pkt->type == DS_REG_NACK) {
		struct ds_reg_nack *np = (struct ds_reg_nack *) pkt;
942
		struct ds_cap_state *cp = find_cap(dp, np->handle);
943
944

		if (!cp) {
945
946
			printk(KERN_ERR "ds-%llu: REG NACK for "
			       "unknown handle %llx\n",
947
			       dp->id, np->handle);
948
949
950
951
952
953
954
955
956
957
958
959
			return 0;
		}
		cp->state = CAP_STATE_UNKNOWN;
	}

	return 0;

conn_reset:
	ds_conn_reset(dp);
	return -ECONNRESET;
}

960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
static void __send_ds_nack(struct ds_info *dp, u64 handle)
{
	struct ds_data_nack nack = {
		.tag = {
			.type = DS_NACK,
			.len = (sizeof(struct ds_data_nack) -
				sizeof(struct ds_msg_tag)),
		},
		.handle = handle,
		.result = DS_INV_HDL,
	};

	__ds_send(dp->lp, &nack, sizeof(nack));
}

static LIST_HEAD(ds_work_list);
static DECLARE_WAIT_QUEUE_HEAD(ds_wait);

struct ds_queue_entry {
	struct list_head		list;
980
	struct ds_info			*dp;
981
982
983
984
985
986
987
988
989
990
991
992
	int				req_len;
	int				__pad;
	u64				req[0];
};

static void process_ds_work(void)
{
	struct ds_queue_entry *qp, *tmp;
	unsigned long flags;
	LIST_HEAD(todo);

	spin_lock_irqsave(&ds_lock, flags);
993
	list_splice_init(&ds_work_list, &todo);
994
995
996
997
	spin_unlock_irqrestore(&ds_lock, flags);

	list_for_each_entry_safe(qp, tmp, &todo, list) {
		struct ds_data *dpkt = (struct ds_data *) qp->req;
998
999
		struct ds_info *dp = qp->dp;
		struct ds_cap_state *cp = find_cap(dp, dpkt->handle);
1000
1001
1002
		int req_len = qp->req_len;

		if (!cp) {
1003
1004
			printk(KERN_ERR "ds-%llu: Data for unknown "
			       "handle %llu\n",
1005
			       dp->id, dpkt->handle);
1006
1007
1008
1009
1010

			spin_lock_irqsave(&ds_lock, flags);
			__send_ds_nack(dp, dpkt->handle);
			spin_unlock_irqrestore(&ds_lock, flags);
		} else {
1011
			cp->data(dp, cp, dpkt, req_len);
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
		}

		list_del(&qp->list);
		kfree(qp);
	}
}

static int ds_thread(void *__unused)
{
	DEFINE_WAIT(wait);

	while (1) {
		prepare_to_wait(&ds_wait, &wait, TASK_INTERRUPTIBLE);
		if (list_empty(&ds_work_list))
			schedule();
		finish_wait(&ds_wait, &wait);

		if (kthread_should_stop())
			break;

		process_ds_work();
	}

	return 0;
}

1038
1039
1040
static int ds_data(struct ds_info *dp, struct ds_msg_tag *pkt, int len)
{
	struct ds_data *dpkt = (struct ds_data *) pkt;
1041
1042
1043
1044
1045
	struct ds_queue_entry *qp;

	qp = kmalloc(sizeof(struct ds_queue_entry) + len, GFP_ATOMIC);
	if (!qp) {
		__send_ds_nack(dp, dpkt->handle);
1046
	} else {
1047
		qp->dp = dp;
1048
1049
1050
		memcpy(&qp->req, pkt, len);
		list_add_tail(&qp->list, &ds_work_list);
		wake_up(&ds_wait);
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
	}
	return 0;
}

static void ds_up(struct ds_info *dp)
{
	struct ldc_channel *lp = dp->lp;
	struct ds_ver_req req;
	int err;

	req.tag.type = DS_INIT_REQ;
	req.tag.len = sizeof(req) - sizeof(struct ds_msg_tag);
	req.ver.major = 1;
	req.ver.minor = 0;

1066
	err = __ds_send(lp, &req, sizeof(req));
1067
1068
1069
1070
	if (err > 0)
		dp->hs_state = DS_HS_START;
}

1071
1072
1073
1074
1075
1076
static void ds_reset(struct ds_info *dp)
{
	int i;

	dp->hs_state = 0;

1077
1078
	for (i = 0; i < dp->num_ds_states; i++) {
		struct ds_cap_state *cp = &dp->ds_states[i];
1079
1080
1081
1082
1083

		cp->state = CAP_STATE_UNKNOWN;
	}
}

1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
static void ds_event(void *arg, int event)
{
	struct ds_info *dp = arg;
	struct ldc_channel *lp = dp->lp;
	unsigned long flags;
	int err;

	spin_lock_irqsave(&ds_lock, flags);

	if (event == LDC_EVENT_UP) {
		ds_up(dp);
		spin_unlock_irqrestore(&ds_lock, flags);
		return;
	}

1099
1100
1101
1102
1103
1104
	if (event == LDC_EVENT_RESET) {
		ds_reset(dp);
		spin_unlock_irqrestore(&ds_lock, flags);
		return;
	}

1105
	if (event != LDC_EVENT_DATA_READY) {
1106
		printk(KERN_WARNING "ds-%llu: Unexpected LDC event %d\n",
1107
		       dp->id, event);
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
		spin_unlock_irqrestore(&ds_lock, flags);
		return;
	}

	err = 0;
	while (1) {
		struct ds_msg_tag *tag;

		err = ldc_read(lp, dp->rcv_buf, sizeof(*tag));

		if (unlikely(err < 0)) {
			if (err == -ECONNRESET)
				ds_conn_reset(dp);
			break;
		}
		if (err == 0)
			break;

		tag = dp->rcv_buf;
		err = ldc_read(lp, tag + 1, tag->len);

		if (unlikely(err < 0)) {
			if (err == -ECONNRESET)
				ds_conn_reset(dp);
			break;
		}
		if (err < tag->len)
			break;

		if (tag->type < DS_DATA)
			err = ds_handshake(dp, dp->rcv_buf);
		else
			err = ds_data(dp, dp->rcv_buf,
				      sizeof(*tag) + err);
		if (err == -ECONNRESET)
			break;
	}

	spin_unlock_irqrestore(&ds_lock, flags);
}

static int __devinit ds_probe(struct vio_dev *vdev,
			      const struct vio_device_id *id)
{
	static int ds_version_printed;
	struct ldc_channel_config ds_cfg = {
		.event		= ds_event,
		.mtu		= 4096,
		.mode		= LDC_MODE_STREAM,
	};
1158
	struct mdesc_handle *hp;
1159
1160
	struct ldc_channel *lp;
	struct ds_info *dp;
1161
1162
	const u64 *val;
	int err, i;
1163
1164
1165
1166
1167
1168
1169
1170
1171

	if (ds_version_printed++ == 0)
		printk(KERN_INFO "%s", version);

	dp = kzalloc(sizeof(*dp), GFP_KERNEL);
	err = -ENOMEM;
	if (!dp)
		goto out_err;

1172
1173
1174
1175
1176
1177
	hp = mdesc_grab();
	val = mdesc_get_property(hp, vdev->mp, "id", NULL);
	if (val)
		dp->id = *val;
	mdesc_release(hp);

1178
1179
1180
1181
1182
1183
	dp->rcv_buf = kzalloc(4096, GFP_KERNEL);
	if (!dp->rcv_buf)
		goto out_free_dp;

	dp->rcv_buf_len = 4096;

1184
1185
	dp->ds_states = kmemdup(ds_states_template,
				sizeof(ds_states_template), GFP_KERNEL);
1186
1187
1188
1189
1190
1191
1192
1193
	if (!dp->ds_states)
		goto out_free_rcv_buf;

	dp->num_ds_states = ARRAY_SIZE(ds_states_template);

	for (i = 0; i < dp->num_ds_states; i++)
		dp->ds_states[i].handle = ((u64)i << 32);

1194
1195
	ds_cfg.tx_irq = vdev->tx_irq;
	ds_cfg.rx_irq = vdev->rx_irq;
1196

1197
	lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp);
1198
1199
	if (IS_ERR(lp)) {
		err = PTR_ERR(lp);
1200
		goto out_free_ds_states;
1201
1202
1203
	}
	dp->lp = lp;

1204
	err = ldc_bind(lp, "DS");
1205
1206
1207
	if (err)
		goto out_free_ldc;

1208
1209
1210
1211
	spin_lock_irq(&ds_lock);
	dp->next = ds_info_list;
	ds_info_list = dp;
	spin_unlock_irq(&ds_lock);
1212

1213
1214
1215
1216
1217
	return err;

out_free_ldc:
	ldc_free(dp->lp);

1218
1219
1220
out_free_ds_states:
	kfree(dp->ds_states);

1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
out_free_rcv_buf:
	kfree(dp->rcv_buf);

out_free_dp:
	kfree(dp);

out_err:
	return err;
}

static int ds_remove(struct vio_dev *vdev)
{
	return 0;
}

1236
static const struct vio_device_id ds_match[] = {
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
	{
		.type = "domain-services-port",
	},
	{},
};

static struct vio_driver ds_driver = {
	.id_table	= ds_match,
	.probe		= ds_probe,
	.remove		= ds_remove,
1247
	.name		= "ds",
1248
1249
1250
1251
};

static int __init ds_init(void)
{
1252
1253
	unsigned long hv_ret, major, minor;

1254
1255
1256
1257
1258
1259
1260
	if (tlb_type == hypervisor) {
		hv_ret = sun4v_get_version(HV_GRP_REBOOT_DATA, &major, &minor);
		if (hv_ret == HV_EOK) {
			pr_info("SUN4V: Reboot data supported (maj=%lu,min=%lu).\n",
				major, minor);
			reboot_data_supported = 1;
		}
1261
	}
1262
	kthread_run(ds_thread, NULL, "kldomd");
1263

1264
1265
1266
	return vio_register_driver(&ds_driver);
}

1267
fs_initcall(ds_init);