~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/sparc/kernel/ds.c

Version: ~ [ linux-5.6-rc7 ] ~ [ linux-5.5.11 ] ~ [ linux-5.4.27 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.112 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.174 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.217 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.217 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.82 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* ds.c: Domain Services driver for Logical Domains
  2  *
  3  * Copyright (C) 2007, 2008 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/string.h>
 10 #include <linux/slab.h>
 11 #include <linux/sched.h>
 12 #include <linux/sched/clock.h>
 13 #include <linux/delay.h>
 14 #include <linux/mutex.h>
 15 #include <linux/kthread.h>
 16 #include <linux/reboot.h>
 17 #include <linux/cpu.h>
 18 
 19 #include <asm/hypervisor.h>
 20 #include <asm/ldc.h>
 21 #include <asm/vio.h>
 22 #include <asm/mdesc.h>
 23 #include <asm/head.h>
 24 #include <asm/irq.h>
 25 
 26 #include "kernel.h"
 27 
 28 #define DRV_MODULE_NAME         "ds"
 29 #define PFX DRV_MODULE_NAME     ": "
 30 #define DRV_MODULE_VERSION      "1.0"
 31 #define DRV_MODULE_RELDATE      "Jul 11, 2007"
 32 
 33 static char version[] =
 34         DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 35 MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
 36 MODULE_DESCRIPTION("Sun LDOM domain services driver");
 37 MODULE_LICENSE("GPL");
 38 MODULE_VERSION(DRV_MODULE_VERSION);
 39 
 40 struct ds_msg_tag {
 41         __u32                   type;
 42 #define DS_INIT_REQ             0x00
 43 #define DS_INIT_ACK             0x01
 44 #define DS_INIT_NACK            0x02
 45 #define DS_REG_REQ              0x03
 46 #define DS_REG_ACK              0x04
 47 #define DS_REG_NACK             0x05
 48 #define DS_UNREG_REQ            0x06
 49 #define DS_UNREG_ACK            0x07
 50 #define DS_UNREG_NACK           0x08
 51 #define DS_DATA                 0x09
 52 #define DS_NACK                 0x0a
 53 
 54         __u32                   len;
 55 };
 56 
 57 /* Result codes */
 58 #define DS_OK                   0x00
 59 #define DS_REG_VER_NACK         0x01
 60 #define DS_REG_DUP              0x02
 61 #define DS_INV_HDL              0x03
 62 #define DS_TYPE_UNKNOWN         0x04
 63 
 64 struct ds_version {
 65         __u16                   major;
 66         __u16                   minor;
 67 };
 68 
 69 struct ds_ver_req {
 70         struct ds_msg_tag       tag;
 71         struct ds_version       ver;
 72 };
 73 
 74 struct ds_ver_ack {
 75         struct ds_msg_tag       tag;
 76         __u16                   minor;
 77 };
 78 
 79 struct ds_ver_nack {
 80         struct ds_msg_tag       tag;
 81         __u16                   major;
 82 };
 83 
 84 struct ds_reg_req {
 85         struct ds_msg_tag       tag;
 86         __u64                   handle;
 87         __u16                   major;
 88         __u16                   minor;
 89         char                    svc_id[0];
 90 };
 91 
 92 struct ds_reg_ack {
 93         struct ds_msg_tag       tag;
 94         __u64                   handle;
 95         __u16                   minor;
 96 };
 97 
 98 struct ds_reg_nack {
 99         struct ds_msg_tag       tag;
100         __u64                   handle;
101         __u16                   major;
102 };
103 
104 struct ds_unreg_req {
105         struct ds_msg_tag       tag;
106         __u64                   handle;
107 };
108 
109 struct ds_unreg_ack {
110         struct ds_msg_tag       tag;
111         __u64                   handle;
112 };
113 
114 struct ds_unreg_nack {
115         struct ds_msg_tag       tag;
116         __u64                   handle;
117 };
118 
119 struct ds_data {
120         struct ds_msg_tag       tag;
121         __u64                   handle;
122 };
123 
124 struct ds_data_nack {
125         struct ds_msg_tag       tag;
126         __u64                   handle;
127         __u64                   result;
128 };
129 
130 struct ds_info;
131 struct ds_cap_state {
132         __u64                   handle;
133 
134         void                    (*data)(struct ds_info *dp,
135                                         struct ds_cap_state *cp,
136                                         void *buf, int len);
137 
138         const char              *service_id;
139 
140         u8                      state;
141 #define CAP_STATE_UNKNOWN       0x00
142 #define CAP_STATE_REG_SENT      0x01
143 #define CAP_STATE_REGISTERED    0x02
144 };
145 
146 static void md_update_data(struct ds_info *dp, struct ds_cap_state *cp,
147                            void *buf, int len);
148 static void domain_shutdown_data(struct ds_info *dp,
149                                  struct ds_cap_state *cp,
150                                  void *buf, int len);
151 static void domain_panic_data(struct ds_info *dp,
152                               struct ds_cap_state *cp,
153                               void *buf, int len);
154 #ifdef CONFIG_HOTPLUG_CPU
155 static void dr_cpu_data(struct ds_info *dp,
156                         struct ds_cap_state *cp,
157                         void *buf, int len);
158 #endif
159 static void ds_pri_data(struct ds_info *dp,
160                         struct ds_cap_state *cp,
161                         void *buf, int len);
162 static void ds_var_data(struct ds_info *dp,
163                         struct ds_cap_state *cp,
164                         void *buf, int len);
165 
166 static struct ds_cap_state ds_states_template[] = {
167         {
168                 .service_id     = "md-update",
169                 .data           = md_update_data,
170         },
171         {
172                 .service_id     = "domain-shutdown",
173                 .data           = domain_shutdown_data,
174         },
175         {
176                 .service_id     = "domain-panic",
177                 .data           = domain_panic_data,
178         },
179 #ifdef CONFIG_HOTPLUG_CPU
180         {
181                 .service_id     = "dr-cpu",
182                 .data           = dr_cpu_data,
183         },
184 #endif
185         {
186                 .service_id     = "pri",
187                 .data           = ds_pri_data,
188         },
189         {
190                 .service_id     = "var-config",
191                 .data           = ds_var_data,
192         },
193         {
194                 .service_id     = "var-config-backup",
195                 .data           = ds_var_data,
196         },
197 };
198 
199 static DEFINE_SPINLOCK(ds_lock);
200 
201 struct ds_info {
202         struct ldc_channel      *lp;
203         u8                      hs_state;
204 #define DS_HS_START             0x01
205 #define DS_HS_DONE              0x02
206 
207         u64                     id;
208 
209         void                    *rcv_buf;
210         int                     rcv_buf_len;
211 
212         struct ds_cap_state     *ds_states;
213         int                     num_ds_states;
214 
215         struct ds_info          *next;
216 };
217 
218 static struct ds_info *ds_info_list;
219 
220 static struct ds_cap_state *find_cap(struct ds_info *dp, u64 handle)
221 {
222         unsigned int index = handle >> 32;
223 
224         if (index >= dp->num_ds_states)
225                 return NULL;
226         return &dp->ds_states[index];
227 }
228 
229 static struct ds_cap_state *find_cap_by_string(struct ds_info *dp,
230                                                const char *name)
231 {
232         int i;
233 
234         for (i = 0; i < dp->num_ds_states; i++) {
235                 if (strcmp(dp->ds_states[i].service_id, name))
236                         continue;
237 
238                 return &dp->ds_states[i];
239         }
240         return NULL;
241 }
242 
243 static int __ds_send(struct ldc_channel *lp, void *data, int len)
244 {
245         int err, limit = 1000;
246 
247         err = -EINVAL;
248         while (limit-- > 0) {
249                 err = ldc_write(lp, data, len);
250                 if (!err || (err != -EAGAIN))
251                         break;
252                 udelay(1);
253         }
254 
255         return err;
256 }
257 
258 static int ds_send(struct ldc_channel *lp, void *data, int len)
259 {
260         unsigned long flags;
261         int err;
262 
263         spin_lock_irqsave(&ds_lock, flags);
264         err = __ds_send(lp, data, len);
265         spin_unlock_irqrestore(&ds_lock, flags);
266 
267         return err;
268 }
269 
270 struct ds_md_update_req {
271         __u64                           req_num;
272 };
273 
274 struct ds_md_update_res {
275         __u64                           req_num;
276         __u32                           result;
277 };
278 
279 static void md_update_data(struct ds_info *dp,
280                            struct ds_cap_state *cp,
281                            void *buf, int len)
282 {
283         struct ldc_channel *lp = dp->lp;
284         struct ds_data *dpkt = buf;
285         struct ds_md_update_req *rp;
286         struct {
287                 struct ds_data          data;
288                 struct ds_md_update_res res;
289         } pkt;
290 
291         rp = (struct ds_md_update_req *) (dpkt + 1);
292 
293         printk(KERN_INFO "ds-%llu: Machine description update.\n", dp->id);
294 
295         mdesc_update();
296 
297         memset(&pkt, 0, sizeof(pkt));
298         pkt.data.tag.type = DS_DATA;
299         pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
300         pkt.data.handle = cp->handle;
301         pkt.res.req_num = rp->req_num;
302         pkt.res.result = DS_OK;
303 
304         ds_send(lp, &pkt, sizeof(pkt));
305 }
306 
307 struct ds_shutdown_req {
308         __u64                           req_num;
309         __u32                           ms_delay;
310 };
311 
312 struct ds_shutdown_res {
313         __u64                           req_num;
314         __u32                           result;
315         char                            reason[1];
316 };
317 
318 static void domain_shutdown_data(struct ds_info *dp,
319                                  struct ds_cap_state *cp,
320                                  void *buf, int len)
321 {
322         struct ldc_channel *lp = dp->lp;
323         struct ds_data *dpkt = buf;
324         struct ds_shutdown_req *rp;
325         struct {
326                 struct ds_data          data;
327                 struct ds_shutdown_res  res;
328         } pkt;
329 
330         rp = (struct ds_shutdown_req *) (dpkt + 1);
331 
332         printk(KERN_ALERT "ds-%llu: Shutdown request from "
333                "LDOM manager received.\n", dp->id);
334 
335         memset(&pkt, 0, sizeof(pkt));
336         pkt.data.tag.type = DS_DATA;
337         pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
338         pkt.data.handle = cp->handle;
339         pkt.res.req_num = rp->req_num;
340         pkt.res.result = DS_OK;
341         pkt.res.reason[0] = 0;
342 
343         ds_send(lp, &pkt, sizeof(pkt));
344 
345         orderly_poweroff(true);
346 }
347 
348 struct ds_panic_req {
349         __u64                           req_num;
350 };
351 
352 struct ds_panic_res {
353         __u64                           req_num;
354         __u32                           result;
355         char                            reason[1];
356 };
357 
358 static void domain_panic_data(struct ds_info *dp,
359                               struct ds_cap_state *cp,
360                               void *buf, int len)
361 {
362         struct ldc_channel *lp = dp->lp;
363         struct ds_data *dpkt = buf;
364         struct ds_panic_req *rp;
365         struct {
366                 struct ds_data          data;
367                 struct ds_panic_res     res;
368         } pkt;
369 
370         rp = (struct ds_panic_req *) (dpkt + 1);
371 
372         printk(KERN_ALERT "ds-%llu: Panic request from "
373                "LDOM manager received.\n", dp->id);
374 
375         memset(&pkt, 0, sizeof(pkt));
376         pkt.data.tag.type = DS_DATA;
377         pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
378         pkt.data.handle = cp->handle;
379         pkt.res.req_num = rp->req_num;
380         pkt.res.result = DS_OK;
381         pkt.res.reason[0] = 0;
382 
383         ds_send(lp, &pkt, sizeof(pkt));
384 
385         panic("PANIC requested by LDOM manager.");
386 }
387 
388 #ifdef CONFIG_HOTPLUG_CPU
389 struct dr_cpu_tag {
390         __u64                           req_num;
391         __u32                           type;
392 #define DR_CPU_CONFIGURE                0x43
393 #define DR_CPU_UNCONFIGURE              0x55
394 #define DR_CPU_FORCE_UNCONFIGURE        0x46
395 #define DR_CPU_STATUS                   0x53
396 
397 /* Responses */
398 #define DR_CPU_OK                       0x6f
399 #define DR_CPU_ERROR                    0x65
400 
401         __u32                           num_records;
402 };
403 
404 struct dr_cpu_resp_entry {
405         __u32                           cpu;
406         __u32                           result;
407 #define DR_CPU_RES_OK                   0x00
408 #define DR_CPU_RES_FAILURE              0x01
409 #define DR_CPU_RES_BLOCKED              0x02
410 #define DR_CPU_RES_CPU_NOT_RESPONDING   0x03
411 #define DR_CPU_RES_NOT_IN_MD            0x04
412 
413         __u32                           stat;
414 #define DR_CPU_STAT_NOT_PRESENT         0x00
415 #define DR_CPU_STAT_UNCONFIGURED        0x01
416 #define DR_CPU_STAT_CONFIGURED          0x02
417 
418         __u32                           str_off;
419 };
420 
421 static void __dr_cpu_send_error(struct ds_info *dp,
422                                 struct ds_cap_state *cp,
423                                 struct ds_data *data)
424 {
425         struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1);
426         struct {
427                 struct ds_data          data;
428                 struct dr_cpu_tag       tag;
429         } pkt;
430         int msg_len;
431 
432         memset(&pkt, 0, sizeof(pkt));
433         pkt.data.tag.type = DS_DATA;
434         pkt.data.handle = cp->handle;
435         pkt.tag.req_num = tag->req_num;
436         pkt.tag.type = DR_CPU_ERROR;
437         pkt.tag.num_records = 0;
438 
439         msg_len = (sizeof(struct ds_data) +
440                    sizeof(struct dr_cpu_tag));
441 
442         pkt.data.tag.len = msg_len - sizeof(struct ds_msg_tag);
443 
444         __ds_send(dp->lp, &pkt, msg_len);
445 }
446 
447 static void dr_cpu_send_error(struct ds_info *dp,
448                               struct ds_cap_state *cp,
449                               struct ds_data *data)
450 {
451         unsigned long flags;
452 
453         spin_lock_irqsave(&ds_lock, flags);
454         __dr_cpu_send_error(dp, cp, data);
455         spin_unlock_irqrestore(&ds_lock, flags);
456 }
457 
458 #define CPU_SENTINEL    0xffffffff
459 
460 static void purge_dups(u32 *list, u32 num_ents)
461 {
462         unsigned int i;
463 
464         for (i = 0; i < num_ents; i++) {
465                 u32 cpu = list[i];
466                 unsigned int j;
467 
468                 if (cpu == CPU_SENTINEL)
469                         continue;
470 
471                 for (j = i + 1; j < num_ents; j++) {
472                         if (list[j] == cpu)
473                                 list[j] = CPU_SENTINEL;
474                 }
475         }
476 }
477 
478 static int dr_cpu_size_response(int ncpus)
479 {
480         return (sizeof(struct ds_data) +
481                 sizeof(struct dr_cpu_tag) +
482                 (sizeof(struct dr_cpu_resp_entry) * ncpus));
483 }
484 
485 static void dr_cpu_init_response(struct ds_data *resp, u64 req_num,
486                                  u64 handle, int resp_len, int ncpus,
487                                  cpumask_t *mask, u32 default_stat)
488 {
489         struct dr_cpu_resp_entry *ent;
490         struct dr_cpu_tag *tag;
491         int i, cpu;
492 
493         tag = (struct dr_cpu_tag *) (resp + 1);
494         ent = (struct dr_cpu_resp_entry *) (tag + 1);
495 
496         resp->tag.type = DS_DATA;
497         resp->tag.len = resp_len - sizeof(struct ds_msg_tag);
498         resp->handle = handle;
499         tag->req_num = req_num;
500         tag->type = DR_CPU_OK;
501         tag->num_records = ncpus;
502 
503         i = 0;
504         for_each_cpu(cpu, mask) {
505                 ent[i].cpu = cpu;
506                 ent[i].result = DR_CPU_RES_OK;
507                 ent[i].stat = default_stat;
508                 i++;
509         }
510         BUG_ON(i != ncpus);
511 }
512 
513 static void dr_cpu_mark(struct ds_data *resp, int cpu, int ncpus,
514                         u32 res, u32 stat)
515 {
516         struct dr_cpu_resp_entry *ent;
517         struct dr_cpu_tag *tag;
518         int i;
519 
520         tag = (struct dr_cpu_tag *) (resp + 1);
521         ent = (struct dr_cpu_resp_entry *) (tag + 1);
522 
523         for (i = 0; i < ncpus; i++) {
524                 if (ent[i].cpu != cpu)
525                         continue;
526                 ent[i].result = res;
527                 ent[i].stat = stat;
528                 break;
529         }
530 }
531 
532 static int dr_cpu_configure(struct ds_info *dp, struct ds_cap_state *cp,
533                             u64 req_num, cpumask_t *mask)
534 {
535         struct ds_data *resp;
536         int resp_len, ncpus, cpu;
537         unsigned long flags;
538 
539         ncpus = cpumask_weight(mask);
540         resp_len = dr_cpu_size_response(ncpus);
541         resp = kzalloc(resp_len, GFP_KERNEL);
542         if (!resp)
543                 return -ENOMEM;
544 
545         dr_cpu_init_response(resp, req_num, cp->handle,
546                              resp_len, ncpus, mask,
547                              DR_CPU_STAT_CONFIGURED);
548 
549         mdesc_populate_present_mask(mask);
550         mdesc_fill_in_cpu_data(mask);
551 
552         for_each_cpu(cpu, mask) {
553                 int err;
554 
555                 printk(KERN_INFO "ds-%llu: Starting cpu %d...\n",
556                        dp->id, cpu);
557                 err = cpu_up(cpu);
558                 if (err) {
559                         __u32 res = DR_CPU_RES_FAILURE;
560                         __u32 stat = DR_CPU_STAT_UNCONFIGURED;
561 
562                         if (!cpu_present(cpu)) {
563                                 /* CPU not present in MD */
564                                 res = DR_CPU_RES_NOT_IN_MD;
565                                 stat = DR_CPU_STAT_NOT_PRESENT;
566                         } else if (err == -ENODEV) {
567                                 /* CPU did not call in successfully */
568                                 res = DR_CPU_RES_CPU_NOT_RESPONDING;
569                         }
570 
571                         printk(KERN_INFO "ds-%llu: CPU startup failed err=%d\n",
572                                dp->id, err);
573                         dr_cpu_mark(resp, cpu, ncpus, res, stat);
574                 }
575         }
576 
577         spin_lock_irqsave(&ds_lock, flags);
578         __ds_send(dp->lp, resp, resp_len);
579         spin_unlock_irqrestore(&ds_lock, flags);
580 
581         kfree(resp);
582 
583         /* Redistribute IRQs, taking into account the new cpus.  */
584         fixup_irqs();
585 
586         return 0;
587 }
588 
589 static int dr_cpu_unconfigure(struct ds_info *dp,
590                               struct ds_cap_state *cp,
591                               u64 req_num,
592                               cpumask_t *mask)
593 {
594         struct ds_data *resp;
595         int resp_len, ncpus, cpu;
596         unsigned long flags;
597 
598         ncpus = cpumask_weight(mask);
599         resp_len = dr_cpu_size_response(ncpus);
600         resp = kzalloc(resp_len, GFP_KERNEL);
601         if (!resp)
602                 return -ENOMEM;
603 
604         dr_cpu_init_response(resp, req_num, cp->handle,
605                              resp_len, ncpus, mask,
606                              DR_CPU_STAT_UNCONFIGURED);
607 
608         for_each_cpu(cpu, mask) {
609                 int err;
610 
611                 printk(KERN_INFO "ds-%llu: Shutting down cpu %d...\n",
612                        dp->id, cpu);
613                 err = cpu_down(cpu);
614                 if (err)
615                         dr_cpu_mark(resp, cpu, ncpus,
616                                     DR_CPU_RES_FAILURE,
617                                     DR_CPU_STAT_CONFIGURED);
618         }
619 
620         spin_lock_irqsave(&ds_lock, flags);
621         __ds_send(dp->lp, resp, resp_len);
622         spin_unlock_irqrestore(&ds_lock, flags);
623 
624         kfree(resp);
625 
626         return 0;
627 }
628 
629 static void dr_cpu_data(struct ds_info *dp, struct ds_cap_state *cp, void *buf,
630                         int len)
631 {
632         struct ds_data *data = buf;
633         struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1);
634         u32 *cpu_list = (u32 *) (tag + 1);
635         u64 req_num = tag->req_num;
636         cpumask_t mask;
637         unsigned int i;
638         int err;
639 
640         switch (tag->type) {
641         case DR_CPU_CONFIGURE:
642         case DR_CPU_UNCONFIGURE:
643         case DR_CPU_FORCE_UNCONFIGURE:
644                 break;
645 
646         default:
647                 dr_cpu_send_error(dp, cp, data);
648                 return;
649         }
650 
651         purge_dups(cpu_list, tag->num_records);
652 
653         cpumask_clear(&mask);
654         for (i = 0; i < tag->num_records; i++) {
655                 if (cpu_list[i] == CPU_SENTINEL)
656                         continue;
657 
658                 if (cpu_list[i] < nr_cpu_ids)
659                         cpumask_set_cpu(cpu_list[i], &mask);
660         }
661 
662         if (tag->type == DR_CPU_CONFIGURE)
663                 err = dr_cpu_configure(dp, cp, req_num, &mask);
664         else
665                 err = dr_cpu_unconfigure(dp, cp, req_num, &mask);
666 
667         if (err)
668                 dr_cpu_send_error(dp, cp, data);
669 }
670 #endif /* CONFIG_HOTPLUG_CPU */
671 
672 struct ds_pri_msg {
673         __u64                           req_num;
674         __u64                           type;
675 #define DS_PRI_REQUEST                  0x00
676 #define DS_PRI_DATA                     0x01
677 #define DS_PRI_UPDATE                   0x02
678 };
679 
680 static void ds_pri_data(struct ds_info *dp,
681                         struct ds_cap_state *cp,
682                         void *buf, int len)
683 {
684         struct ds_data *dpkt = buf;
685         struct ds_pri_msg *rp;
686 
687         rp = (struct ds_pri_msg *) (dpkt + 1);
688 
689         printk(KERN_INFO "ds-%llu: PRI REQ [%llx:%llx], len=%d\n",
690                dp->id, rp->req_num, rp->type, len);
691 }
692 
693 struct ds_var_hdr {
694         __u32                           type;
695 #define DS_VAR_SET_REQ                  0x00
696 #define DS_VAR_DELETE_REQ               0x01
697 #define DS_VAR_SET_RESP                 0x02
698 #define DS_VAR_DELETE_RESP              0x03
699 };
700 
701 struct ds_var_set_msg {
702         struct ds_var_hdr               hdr;
703         char                            name_and_value[0];
704 };
705 
706 struct ds_var_delete_msg {
707         struct ds_var_hdr               hdr;
708         char                            name[0];
709 };
710 
711 struct ds_var_resp {
712         struct ds_var_hdr               hdr;
713         __u32                           result;
714 #define DS_VAR_SUCCESS                  0x00
715 #define DS_VAR_NO_SPACE                 0x01
716 #define DS_VAR_INVALID_VAR              0x02
717 #define DS_VAR_INVALID_VAL              0x03
718 #define DS_VAR_NOT_PRESENT              0x04
719 };
720 
721 static DEFINE_MUTEX(ds_var_mutex);
722 static int ds_var_doorbell;
723 static int ds_var_response;
724 
725 static void ds_var_data(struct ds_info *dp,
726                         struct ds_cap_state *cp,
727                         void *buf, int len)
728 {
729         struct ds_data *dpkt = buf;
730         struct ds_var_resp *rp;
731 
732         rp = (struct ds_var_resp *) (dpkt + 1);
733 
734         if (rp->hdr.type != DS_VAR_SET_RESP &&
735             rp->hdr.type != DS_VAR_DELETE_RESP)
736                 return;
737 
738         ds_var_response = rp->result;
739         wmb();
740         ds_var_doorbell = 1;
741 }
742 
743 void ldom_set_var(const char *var, const char *value)
744 {
745         struct ds_cap_state *cp;
746         struct ds_info *dp;
747         unsigned long flags;
748 
749         spin_lock_irqsave(&ds_lock, flags);
750         cp = NULL;
751         for (dp = ds_info_list; dp; dp = dp->next) {
752                 struct ds_cap_state *tmp;
753 
754                 tmp = find_cap_by_string(dp, "var-config");
755                 if (tmp && tmp->state == CAP_STATE_REGISTERED) {
756                         cp = tmp;
757                         break;
758                 }
759         }
760         if (!cp) {
761                 for (dp = ds_info_list; dp; dp = dp->next) {
762                         struct ds_cap_state *tmp;
763 
764                         tmp = find_cap_by_string(dp, "var-config-backup");
765                         if (tmp && tmp->state == CAP_STATE_REGISTERED) {
766                                 cp = tmp;
767                                 break;
768                         }
769                 }
770         }
771         spin_unlock_irqrestore(&ds_lock, flags);
772 
773         if (cp) {
774                 union {
775                         struct {
776                                 struct ds_data          data;
777                                 struct ds_var_set_msg   msg;
778                         } header;
779                         char                    all[512];
780                 } pkt;
781                 char  *base, *p;
782                 int msg_len, loops;
783 
784                 if (strlen(var) + strlen(value) + 2 >
785                     sizeof(pkt) - sizeof(pkt.header)) {
786                         printk(KERN_ERR PFX
787                                 "contents length: %zu, which more than max: %lu,"
788                                 "so could not set (%s) variable to (%s).\n",
789                                 strlen(var) + strlen(value) + 2,
790                                 sizeof(pkt) - sizeof(pkt.header), var, value);
791                         return;
792                 }
793 
794                 memset(&pkt, 0, sizeof(pkt));
795                 pkt.header.data.tag.type = DS_DATA;
796                 pkt.header.data.handle = cp->handle;
797                 pkt.header.msg.hdr.type = DS_VAR_SET_REQ;
798                 base = p = &pkt.header.msg.name_and_value[0];
799                 strcpy(p, var);
800                 p += strlen(var) + 1;
801                 strcpy(p, value);
802                 p += strlen(value) + 1;
803 
804                 msg_len = (sizeof(struct ds_data) +
805                            sizeof(struct ds_var_set_msg) +
806                            (p - base));
807                 msg_len = (msg_len + 3) & ~3;
808                 pkt.header.data.tag.len = msg_len - sizeof(struct ds_msg_tag);
809 
810                 mutex_lock(&ds_var_mutex);
811 
812                 spin_lock_irqsave(&ds_lock, flags);
813                 ds_var_doorbell = 0;
814                 ds_var_response = -1;
815 
816                 __ds_send(dp->lp, &pkt, msg_len);
817                 spin_unlock_irqrestore(&ds_lock, flags);
818 
819                 loops = 1000;
820                 while (ds_var_doorbell == 0) {
821                         if (loops-- < 0)
822                                 break;
823                         barrier();
824                         udelay(100);
825                 }
826 
827                 mutex_unlock(&ds_var_mutex);
828 
829                 if (ds_var_doorbell == 0 ||
830                     ds_var_response != DS_VAR_SUCCESS)
831                         printk(KERN_ERR "ds-%llu: var-config [%s:%s] "
832                                "failed, response(%d).\n",
833                                dp->id, var, value,
834                                ds_var_response);
835         } else {
836                 printk(KERN_ERR PFX "var-config not registered so "
837                        "could not set (%s) variable to (%s).\n",
838                        var, value);
839         }
840 }
841 
842 static char full_boot_str[256] __attribute__((aligned(32)));
843 static int reboot_data_supported;
844 
845 void ldom_reboot(const char *boot_command)
846 {
847         /* Don't bother with any of this if the boot_command
848          * is empty.
849          */
850         if (boot_command && strlen(boot_command)) {
851                 unsigned long len;
852 
853                 snprintf(full_boot_str, sizeof(full_boot_str), "boot %s",
854                          boot_command);
855                 len = strlen(full_boot_str);
856 
857                 if (reboot_data_supported) {
858                         unsigned long ra = kimage_addr_to_ra(full_boot_str);
859                         unsigned long hv_ret;
860 
861                         hv_ret = sun4v_reboot_data_set(ra, len);
862                         if (hv_ret != HV_EOK)
863                                 pr_err("SUN4V: Unable to set reboot data "
864                                        "hv_ret=%lu\n", hv_ret);
865                 } else {
866                         ldom_set_var("reboot-command", full_boot_str);
867                 }
868         }
869         sun4v_mach_sir();
870 }
871 
872 void ldom_power_off(void)
873 {
874         sun4v_mach_exit(0);
875 }
876 
877 static void ds_conn_reset(struct ds_info *dp)
878 {
879         printk(KERN_ERR "ds-%llu: ds_conn_reset() from %pf\n",
880                dp->id, __builtin_return_address(0));
881 }
882 
883 static int register_services(struct ds_info *dp)
884 {
885         struct ldc_channel *lp = dp->lp;
886         int i;
887 
888         for (i = 0; i < dp->num_ds_states; i++) {
889                 struct {
890                         struct ds_reg_req req;
891                         u8 id_buf[256];
892                 } pbuf;
893                 struct ds_cap_state *cp = &dp->ds_states[i];
894                 int err, msg_len;
895                 u64 new_count;
896 
897                 if (cp->state == CAP_STATE_REGISTERED)
898                         continue;
899 
900                 new_count = sched_clock() & 0xffffffff;
901                 cp->handle = ((u64) i << 32) | new_count;
902 
903                 msg_len = (sizeof(struct ds_reg_req) +
904                            strlen(cp->service_id));
905 
906                 memset(&pbuf, 0, sizeof(pbuf));
907                 pbuf.req.tag.type = DS_REG_REQ;
908                 pbuf.req.tag.len = (msg_len - sizeof(struct ds_msg_tag));
909                 pbuf.req.handle = cp->handle;
910                 pbuf.req.major = 1;
911                 pbuf.req.minor = 0;
912                 strcpy(pbuf.id_buf, cp->service_id);
913 
914                 err = __ds_send(lp, &pbuf, msg_len);
915                 if (err > 0)
916                         cp->state = CAP_STATE_REG_SENT;
917         }
918         return 0;
919 }
920 
921 static int ds_handshake(struct ds_info *dp, struct ds_msg_tag *pkt)
922 {
923 
924         if (dp->hs_state == DS_HS_START) {
925                 if (pkt->type != DS_INIT_ACK)
926                         goto conn_reset;
927 
928                 dp->hs_state = DS_HS_DONE;
929 
930                 return register_services(dp);
931         }
932 
933         if (dp->hs_state != DS_HS_DONE)
934                 goto conn_reset;
935 
936         if (pkt->type == DS_REG_ACK) {
937                 struct ds_reg_ack *ap = (struct ds_reg_ack *) pkt;
938                 struct ds_cap_state *cp = find_cap(dp, ap->handle);
939 
940                 if (!cp) {
941                         printk(KERN_ERR "ds-%llu: REG ACK for unknown "
942                                "handle %llx\n", dp->id, ap->handle);
943                         return 0;
944                 }
945                 printk(KERN_INFO "ds-%llu: Registered %s service.\n",
946                        dp->id, cp->service_id);
947                 cp->state = CAP_STATE_REGISTERED;
948         } else if (pkt->type == DS_REG_NACK) {
949                 struct ds_reg_nack *np = (struct ds_reg_nack *) pkt;
950                 struct ds_cap_state *cp = find_cap(dp, np->handle);
951 
952                 if (!cp) {
953                         printk(KERN_ERR "ds-%llu: REG NACK for "
954                                "unknown handle %llx\n",
955                                dp->id, np->handle);
956                         return 0;
957                 }
958                 cp->state = CAP_STATE_UNKNOWN;
959         }
960 
961         return 0;
962 
963 conn_reset:
964         ds_conn_reset(dp);
965         return -ECONNRESET;
966 }
967 
968 static void __send_ds_nack(struct ds_info *dp, u64 handle)
969 {
970         struct ds_data_nack nack = {
971                 .tag = {
972                         .type = DS_NACK,
973                         .len = (sizeof(struct ds_data_nack) -
974                                 sizeof(struct ds_msg_tag)),
975                 },
976                 .handle = handle,
977                 .result = DS_INV_HDL,
978         };
979 
980         __ds_send(dp->lp, &nack, sizeof(nack));
981 }
982 
983 static LIST_HEAD(ds_work_list);
984 static DECLARE_WAIT_QUEUE_HEAD(ds_wait);
985 
986 struct ds_queue_entry {
987         struct list_head                list;
988         struct ds_info                  *dp;
989         int                             req_len;
990         int                             __pad;
991         u64                             req[0];
992 };
993 
994 static void process_ds_work(void)
995 {
996         struct ds_queue_entry *qp, *tmp;
997         unsigned long flags;
998         LIST_HEAD(todo);
999 
1000         spin_lock_irqsave(&ds_lock, flags);
1001         list_splice_init(&ds_work_list, &todo);
1002         spin_unlock_irqrestore(&ds_lock, flags);
1003 
1004         list_for_each_entry_safe(qp, tmp, &todo, list) {
1005                 struct ds_data *dpkt = (struct ds_data *) qp->req;
1006                 struct ds_info *dp = qp->dp;
1007                 struct ds_cap_state *cp = find_cap(dp, dpkt->handle);
1008                 int req_len = qp->req_len;
1009 
1010                 if (!cp) {
1011                         printk(KERN_ERR "ds-%llu: Data for unknown "
1012                                "handle %llu\n",
1013                                dp->id, dpkt->handle);
1014 
1015                         spin_lock_irqsave(&ds_lock, flags);
1016                         __send_ds_nack(dp, dpkt->handle);
1017                         spin_unlock_irqrestore(&ds_lock, flags);
1018                 } else {
1019                         cp->data(dp, cp, dpkt, req_len);
1020                 }
1021 
1022                 list_del(&qp->list);
1023                 kfree(qp);
1024         }
1025 }
1026 
1027 static int ds_thread(void *__unused)
1028 {
1029         DEFINE_WAIT(wait);
1030 
1031         while (1) {
1032                 prepare_to_wait(&ds_wait, &wait, TASK_INTERRUPTIBLE);
1033                 if (list_empty(&ds_work_list))
1034                         schedule();
1035                 finish_wait(&ds_wait, &wait);
1036 
1037                 if (kthread_should_stop())
1038                         break;
1039 
1040                 process_ds_work();
1041         }
1042 
1043         return 0;
1044 }
1045 
1046 static int ds_data(struct ds_info *dp, struct ds_msg_tag *pkt, int len)
1047 {
1048         struct ds_data *dpkt = (struct ds_data *) pkt;
1049         struct ds_queue_entry *qp;
1050 
1051         qp = kmalloc(sizeof(struct ds_queue_entry) + len, GFP_ATOMIC);
1052         if (!qp) {
1053                 __send_ds_nack(dp, dpkt->handle);
1054         } else {
1055                 qp->dp = dp;
1056                 memcpy(&qp->req, pkt, len);
1057                 list_add_tail(&qp->list, &ds_work_list);
1058                 wake_up(&ds_wait);
1059         }
1060         return 0;
1061 }
1062 
1063 static void ds_up(struct ds_info *dp)
1064 {
1065         struct ldc_channel *lp = dp->lp;
1066         struct ds_ver_req req;
1067         int err;
1068 
1069         req.tag.type = DS_INIT_REQ;
1070         req.tag.len = sizeof(req) - sizeof(struct ds_msg_tag);
1071         req.ver.major = 1;
1072         req.ver.minor = 0;
1073 
1074         err = __ds_send(lp, &req, sizeof(req));
1075         if (err > 0)
1076                 dp->hs_state = DS_HS_START;
1077 }
1078 
1079 static void ds_reset(struct ds_info *dp)
1080 {
1081         int i;
1082 
1083         dp->hs_state = 0;
1084 
1085         for (i = 0; i < dp->num_ds_states; i++) {
1086                 struct ds_cap_state *cp = &dp->ds_states[i];
1087 
1088                 cp->state = CAP_STATE_UNKNOWN;
1089         }
1090 }
1091 
1092 static void ds_event(void *arg, int event)
1093 {
1094         struct ds_info *dp = arg;
1095         struct ldc_channel *lp = dp->lp;
1096         unsigned long flags;
1097         int err;
1098 
1099         spin_lock_irqsave(&ds_lock, flags);
1100 
1101         if (event == LDC_EVENT_UP) {
1102                 ds_up(dp);
1103                 spin_unlock_irqrestore(&ds_lock, flags);
1104                 return;
1105         }
1106 
1107         if (event == LDC_EVENT_RESET) {
1108                 ds_reset(dp);
1109                 spin_unlock_irqrestore(&ds_lock, flags);
1110                 return;
1111         }
1112 
1113         if (event != LDC_EVENT_DATA_READY) {
1114                 printk(KERN_WARNING "ds-%llu: Unexpected LDC event %d\n",
1115                        dp->id, event);
1116                 spin_unlock_irqrestore(&ds_lock, flags);
1117                 return;
1118         }
1119 
1120         err = 0;
1121         while (1) {
1122                 struct ds_msg_tag *tag;
1123 
1124                 err = ldc_read(lp, dp->rcv_buf, sizeof(*tag));
1125 
1126                 if (unlikely(err < 0)) {
1127                         if (err == -ECONNRESET)
1128                                 ds_conn_reset(dp);
1129                         break;
1130                 }
1131                 if (err == 0)
1132                         break;
1133 
1134                 tag = dp->rcv_buf;
1135                 err = ldc_read(lp, tag + 1, tag->len);
1136 
1137                 if (unlikely(err < 0)) {
1138                         if (err == -ECONNRESET)
1139                                 ds_conn_reset(dp);
1140                         break;
1141                 }
1142                 if (err < tag->len)
1143                         break;
1144 
1145                 if (tag->type < DS_DATA)
1146                         err = ds_handshake(dp, dp->rcv_buf);
1147                 else
1148                         err = ds_data(dp, dp->rcv_buf,
1149                                       sizeof(*tag) + err);
1150                 if (err == -ECONNRESET)
1151                         break;
1152         }
1153 
1154         spin_unlock_irqrestore(&ds_lock, flags);
1155 }
1156 
1157 static int ds_probe(struct vio_dev *vdev, const struct vio_device_id *id)
1158 {
1159         static int ds_version_printed;
1160         struct ldc_channel_config ds_cfg = {
1161                 .event          = ds_event,
1162                 .mtu            = 4096,
1163                 .mode           = LDC_MODE_STREAM,
1164         };
1165         struct mdesc_handle *hp;
1166         struct ldc_channel *lp;
1167         struct ds_info *dp;
1168         const u64 *val;
1169         int err, i;
1170 
1171         if (ds_version_printed++ == 0)
1172                 printk(KERN_INFO "%s", version);
1173 
1174         dp = kzalloc(sizeof(*dp), GFP_KERNEL);
1175         err = -ENOMEM;
1176         if (!dp)
1177                 goto out_err;
1178 
1179         hp = mdesc_grab();
1180         val = mdesc_get_property(hp, vdev->mp, "id", NULL);
1181         if (val)
1182                 dp->id = *val;
1183         mdesc_release(hp);
1184 
1185         dp->rcv_buf = kzalloc(4096, GFP_KERNEL);
1186         if (!dp->rcv_buf)
1187                 goto out_free_dp;
1188 
1189         dp->rcv_buf_len = 4096;
1190 
1191         dp->ds_states = kmemdup(ds_states_template,
1192                                 sizeof(ds_states_template), GFP_KERNEL);
1193         if (!dp->ds_states)
1194                 goto out_free_rcv_buf;
1195 
1196         dp->num_ds_states = ARRAY_SIZE(ds_states_template);
1197 
1198         for (i = 0; i < dp->num_ds_states; i++)
1199                 dp->ds_states[i].handle = ((u64)i << 32);
1200 
1201         ds_cfg.tx_irq = vdev->tx_irq;
1202         ds_cfg.rx_irq = vdev->rx_irq;
1203 
1204         lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp, "DS");
1205         if (IS_ERR(lp)) {
1206                 err = PTR_ERR(lp);
1207                 goto out_free_ds_states;
1208         }
1209         dp->lp = lp;
1210 
1211         err = ldc_bind(lp);
1212         if (err)
1213                 goto out_free_ldc;
1214 
1215         spin_lock_irq(&ds_lock);
1216         dp->next = ds_info_list;
1217         ds_info_list = dp;
1218         spin_unlock_irq(&ds_lock);
1219 
1220         return err;
1221 
1222 out_free_ldc:
1223         ldc_free(dp->lp);
1224 
1225 out_free_ds_states:
1226         kfree(dp->ds_states);
1227 
1228 out_free_rcv_buf:
1229         kfree(dp->rcv_buf);
1230 
1231 out_free_dp:
1232         kfree(dp);
1233 
1234 out_err:
1235         return err;
1236 }
1237 
1238 static int ds_remove(struct vio_dev *vdev)
1239 {
1240         return 0;
1241 }
1242 
1243 static const struct vio_device_id ds_match[] = {
1244         {
1245                 .type = "domain-services-port",
1246         },
1247         {},
1248 };
1249 
1250 static struct vio_driver ds_driver = {
1251         .id_table       = ds_match,
1252         .probe          = ds_probe,
1253         .remove         = ds_remove,
1254         .name           = "ds",
1255 };
1256 
1257 static int __init ds_init(void)
1258 {
1259         unsigned long hv_ret, major, minor;
1260 
1261         if (tlb_type == hypervisor) {
1262                 hv_ret = sun4v_get_version(HV_GRP_REBOOT_DATA, &major, &minor);
1263                 if (hv_ret == HV_EOK) {
1264                         pr_info("SUN4V: Reboot data supported (maj=%lu,min=%lu).\n",
1265                                 major, minor);
1266                         reboot_data_supported = 1;
1267                 }
1268         }
1269         kthread_run(ds_thread, NULL, "kldomd");
1270 
1271         return vio_register_driver(&ds_driver);
1272 }
1273 
1274 fs_initcall(ds_init);
1275 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp