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