linux/drivers/s390/char/sclp_cmd.c
<<
>>
Prefs
   1/*
   2 * Copyright IBM Corp. 2007,2012
   3 *
   4 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
   5 *            Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
   6 */
   7
   8#define KMSG_COMPONENT "sclp_cmd"
   9#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  10
  11#include <linux/completion.h>
  12#include <linux/init.h>
  13#include <linux/errno.h>
  14#include <linux/err.h>
  15#include <linux/export.h>
  16#include <linux/slab.h>
  17#include <linux/string.h>
  18#include <linux/mm.h>
  19#include <linux/mmzone.h>
  20#include <linux/memory.h>
  21#include <linux/module.h>
  22#include <linux/platform_device.h>
  23#include <asm/ctl_reg.h>
  24#include <asm/chpid.h>
  25#include <asm/setup.h>
  26#include <asm/page.h>
  27#include <asm/sclp.h>
  28
  29#include "sclp.h"
  30
  31static void sclp_sync_callback(struct sclp_req *req, void *data)
  32{
  33        struct completion *completion = data;
  34
  35        complete(completion);
  36}
  37
  38int sclp_sync_request(sclp_cmdw_t cmd, void *sccb)
  39{
  40        return sclp_sync_request_timeout(cmd, sccb, 0);
  41}
  42
  43int sclp_sync_request_timeout(sclp_cmdw_t cmd, void *sccb, int timeout)
  44{
  45        struct completion completion;
  46        struct sclp_req *request;
  47        int rc;
  48
  49        request = kzalloc(sizeof(*request), GFP_KERNEL);
  50        if (!request)
  51                return -ENOMEM;
  52        if (timeout)
  53                request->queue_timeout = timeout;
  54        request->command = cmd;
  55        request->sccb = sccb;
  56        request->status = SCLP_REQ_FILLED;
  57        request->callback = sclp_sync_callback;
  58        request->callback_data = &completion;
  59        init_completion(&completion);
  60
  61        /* Perform sclp request. */
  62        rc = sclp_add_request(request);
  63        if (rc)
  64                goto out;
  65        wait_for_completion(&completion);
  66
  67        /* Check response. */
  68        if (request->status != SCLP_REQ_DONE) {
  69                pr_warning("sync request failed (cmd=0x%08x, "
  70                           "status=0x%02x)\n", cmd, request->status);
  71                rc = -EIO;
  72        }
  73out:
  74        kfree(request);
  75        return rc;
  76}
  77
  78/*
  79 * CPU configuration related functions.
  80 */
  81
  82#define SCLP_CMDW_READ_CPU_INFO         0x00010001
  83#define SCLP_CMDW_CONFIGURE_CPU         0x00110001
  84#define SCLP_CMDW_DECONFIGURE_CPU       0x00100001
  85
  86struct read_cpu_info_sccb {
  87        struct  sccb_header header;
  88        u16     nr_configured;
  89        u16     offset_configured;
  90        u16     nr_standby;
  91        u16     offset_standby;
  92        u8      reserved[4096 - 16];
  93} __attribute__((packed, aligned(PAGE_SIZE)));
  94
  95static void sclp_fill_core_info(struct sclp_core_info *info,
  96                                struct read_cpu_info_sccb *sccb)
  97{
  98        char *page = (char *) sccb;
  99
 100        memset(info, 0, sizeof(*info));
 101        info->configured = sccb->nr_configured;
 102        info->standby = sccb->nr_standby;
 103        info->combined = sccb->nr_configured + sccb->nr_standby;
 104        memcpy(&info->core, page + sccb->offset_configured,
 105               info->combined * sizeof(struct sclp_core_entry));
 106}
 107
 108int sclp_get_core_info(struct sclp_core_info *info)
 109{
 110        int rc;
 111        struct read_cpu_info_sccb *sccb;
 112
 113        if (!SCLP_HAS_CPU_INFO)
 114                return -EOPNOTSUPP;
 115        sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
 116        if (!sccb)
 117                return -ENOMEM;
 118        sccb->header.length = sizeof(*sccb);
 119        rc = sclp_sync_request_timeout(SCLP_CMDW_READ_CPU_INFO, sccb,
 120                                       SCLP_QUEUE_INTERVAL);
 121        if (rc)
 122                goto out;
 123        if (sccb->header.response_code != 0x0010) {
 124                pr_warning("readcpuinfo failed (response=0x%04x)\n",
 125                           sccb->header.response_code);
 126                rc = -EIO;
 127                goto out;
 128        }
 129        sclp_fill_core_info(info, sccb);
 130out:
 131        free_page((unsigned long) sccb);
 132        return rc;
 133}
 134
 135struct cpu_configure_sccb {
 136        struct sccb_header header;
 137} __attribute__((packed, aligned(8)));
 138
 139static int do_core_configure(sclp_cmdw_t cmd)
 140{
 141        struct cpu_configure_sccb *sccb;
 142        int rc;
 143
 144        if (!SCLP_HAS_CPU_RECONFIG)
 145                return -EOPNOTSUPP;
 146        /*
 147         * This is not going to cross a page boundary since we force
 148         * kmalloc to have a minimum alignment of 8 bytes on s390.
 149         */
 150        sccb = kzalloc(sizeof(*sccb), GFP_KERNEL | GFP_DMA);
 151        if (!sccb)
 152                return -ENOMEM;
 153        sccb->header.length = sizeof(*sccb);
 154        rc = sclp_sync_request_timeout(cmd, sccb, SCLP_QUEUE_INTERVAL);
 155        if (rc)
 156                goto out;
 157        switch (sccb->header.response_code) {
 158        case 0x0020:
 159        case 0x0120:
 160                break;
 161        default:
 162                pr_warning("configure cpu failed (cmd=0x%08x, "
 163                           "response=0x%04x)\n", cmd,
 164                           sccb->header.response_code);
 165                rc = -EIO;
 166                break;
 167        }
 168out:
 169        kfree(sccb);
 170        return rc;
 171}
 172
 173int sclp_core_configure(u8 core)
 174{
 175        return do_core_configure(SCLP_CMDW_CONFIGURE_CPU | core << 8);
 176}
 177
 178int sclp_core_deconfigure(u8 core)
 179{
 180        return do_core_configure(SCLP_CMDW_DECONFIGURE_CPU | core << 8);
 181}
 182
 183#ifdef CONFIG_MEMORY_HOTPLUG
 184
 185static DEFINE_MUTEX(sclp_mem_mutex);
 186static LIST_HEAD(sclp_mem_list);
 187static u8 sclp_max_storage_id;
 188static DECLARE_BITMAP(sclp_storage_ids, 256);
 189static int sclp_mem_state_changed;
 190
 191struct memory_increment {
 192        struct list_head list;
 193        u16 rn;
 194        int standby;
 195};
 196
 197struct assign_storage_sccb {
 198        struct sccb_header header;
 199        u16 rn;
 200} __packed;
 201
 202int arch_get_memory_phys_device(unsigned long start_pfn)
 203{
 204        if (!sclp.rzm)
 205                return 0;
 206        return PFN_PHYS(start_pfn) >> ilog2(sclp.rzm);
 207}
 208
 209static unsigned long long rn2addr(u16 rn)
 210{
 211        return (unsigned long long) (rn - 1) * sclp.rzm;
 212}
 213
 214static int do_assign_storage(sclp_cmdw_t cmd, u16 rn)
 215{
 216        struct assign_storage_sccb *sccb;
 217        int rc;
 218
 219        sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
 220        if (!sccb)
 221                return -ENOMEM;
 222        sccb->header.length = PAGE_SIZE;
 223        sccb->rn = rn;
 224        rc = sclp_sync_request_timeout(cmd, sccb, SCLP_QUEUE_INTERVAL);
 225        if (rc)
 226                goto out;
 227        switch (sccb->header.response_code) {
 228        case 0x0020:
 229        case 0x0120:
 230                break;
 231        default:
 232                pr_warning("assign storage failed (cmd=0x%08x, "
 233                           "response=0x%04x, rn=0x%04x)\n", cmd,
 234                           sccb->header.response_code, rn);
 235                rc = -EIO;
 236                break;
 237        }
 238out:
 239        free_page((unsigned long) sccb);
 240        return rc;
 241}
 242
 243static int sclp_assign_storage(u16 rn)
 244{
 245        unsigned long long start;
 246        int rc;
 247
 248        rc = do_assign_storage(0x000d0001, rn);
 249        if (rc)
 250                return rc;
 251        start = rn2addr(rn);
 252        storage_key_init_range(start, start + sclp.rzm);
 253        return 0;
 254}
 255
 256static int sclp_unassign_storage(u16 rn)
 257{
 258        return do_assign_storage(0x000c0001, rn);
 259}
 260
 261struct attach_storage_sccb {
 262        struct sccb_header header;
 263        u16 :16;
 264        u16 assigned;
 265        u32 :32;
 266        u32 entries[0];
 267} __packed;
 268
 269static int sclp_attach_storage(u8 id)
 270{
 271        struct attach_storage_sccb *sccb;
 272        int rc;
 273        int i;
 274
 275        sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
 276        if (!sccb)
 277                return -ENOMEM;
 278        sccb->header.length = PAGE_SIZE;
 279        rc = sclp_sync_request_timeout(0x00080001 | id << 8, sccb,
 280                                       SCLP_QUEUE_INTERVAL);
 281        if (rc)
 282                goto out;
 283        switch (sccb->header.response_code) {
 284        case 0x0020:
 285                set_bit(id, sclp_storage_ids);
 286                for (i = 0; i < sccb->assigned; i++) {
 287                        if (sccb->entries[i])
 288                                sclp_unassign_storage(sccb->entries[i] >> 16);
 289                }
 290                break;
 291        default:
 292                rc = -EIO;
 293                break;
 294        }
 295out:
 296        free_page((unsigned long) sccb);
 297        return rc;
 298}
 299
 300static int sclp_mem_change_state(unsigned long start, unsigned long size,
 301                                 int online)
 302{
 303        struct memory_increment *incr;
 304        unsigned long long istart;
 305        int rc = 0;
 306
 307        list_for_each_entry(incr, &sclp_mem_list, list) {
 308                istart = rn2addr(incr->rn);
 309                if (start + size - 1 < istart)
 310                        break;
 311                if (start > istart + sclp.rzm - 1)
 312                        continue;
 313                if (online)
 314                        rc |= sclp_assign_storage(incr->rn);
 315                else
 316                        sclp_unassign_storage(incr->rn);
 317                if (rc == 0)
 318                        incr->standby = online ? 0 : 1;
 319        }
 320        return rc ? -EIO : 0;
 321}
 322
 323static bool contains_standby_increment(unsigned long start, unsigned long end)
 324{
 325        struct memory_increment *incr;
 326        unsigned long istart;
 327
 328        list_for_each_entry(incr, &sclp_mem_list, list) {
 329                istart = rn2addr(incr->rn);
 330                if (end - 1 < istart)
 331                        continue;
 332                if (start > istart + sclp.rzm - 1)
 333                        continue;
 334                if (incr->standby)
 335                        return true;
 336        }
 337        return false;
 338}
 339
 340static int sclp_mem_notifier(struct notifier_block *nb,
 341                             unsigned long action, void *data)
 342{
 343        unsigned long start, size;
 344        struct memory_notify *arg;
 345        unsigned char id;
 346        int rc = 0;
 347
 348        arg = data;
 349        start = arg->start_pfn << PAGE_SHIFT;
 350        size = arg->nr_pages << PAGE_SHIFT;
 351        mutex_lock(&sclp_mem_mutex);
 352        for_each_clear_bit(id, sclp_storage_ids, sclp_max_storage_id + 1)
 353                sclp_attach_storage(id);
 354        switch (action) {
 355        case MEM_GOING_OFFLINE:
 356                /*
 357                 * We do not allow to set memory blocks offline that contain
 358                 * standby memory. This is done to simplify the "memory online"
 359                 * case.
 360                 */
 361                if (contains_standby_increment(start, start + size))
 362                        rc = -EPERM;
 363                break;
 364        case MEM_ONLINE:
 365        case MEM_CANCEL_OFFLINE:
 366                break;
 367        case MEM_GOING_ONLINE:
 368                rc = sclp_mem_change_state(start, size, 1);
 369                break;
 370        case MEM_CANCEL_ONLINE:
 371                sclp_mem_change_state(start, size, 0);
 372                break;
 373        case MEM_OFFLINE:
 374                sclp_mem_change_state(start, size, 0);
 375                break;
 376        default:
 377                rc = -EINVAL;
 378                break;
 379        }
 380        if (!rc)
 381                sclp_mem_state_changed = 1;
 382        mutex_unlock(&sclp_mem_mutex);
 383        return rc ? NOTIFY_BAD : NOTIFY_OK;
 384}
 385
 386static struct notifier_block sclp_mem_nb = {
 387        .notifier_call = sclp_mem_notifier,
 388};
 389
 390static void __init align_to_block_size(unsigned long long *start,
 391                                       unsigned long long *size)
 392{
 393        unsigned long long start_align, size_align, alignment;
 394
 395        alignment = memory_block_size_bytes();
 396        start_align = roundup(*start, alignment);
 397        size_align = rounddown(*start + *size, alignment) - start_align;
 398
 399        pr_info("Standby memory at 0x%llx (%lluM of %lluM usable)\n",
 400                *start, size_align >> 20, *size >> 20);
 401        *start = start_align;
 402        *size = size_align;
 403}
 404
 405static void __init add_memory_merged(u16 rn)
 406{
 407        static u16 first_rn, num;
 408        unsigned long long start, size;
 409
 410        if (rn && first_rn && (first_rn + num == rn)) {
 411                num++;
 412                return;
 413        }
 414        if (!first_rn)
 415                goto skip_add;
 416        start = rn2addr(first_rn);
 417        size = (unsigned long long) num * sclp.rzm;
 418        if (start >= VMEM_MAX_PHYS)
 419                goto skip_add;
 420        if (start + size > VMEM_MAX_PHYS)
 421                size = VMEM_MAX_PHYS - start;
 422        if (memory_end_set && (start >= memory_end))
 423                goto skip_add;
 424        if (memory_end_set && (start + size > memory_end))
 425                size = memory_end - start;
 426        align_to_block_size(&start, &size);
 427        if (size)
 428                add_memory(0, start, size);
 429skip_add:
 430        first_rn = rn;
 431        num = 1;
 432}
 433
 434static void __init sclp_add_standby_memory(void)
 435{
 436        struct memory_increment *incr;
 437
 438        list_for_each_entry(incr, &sclp_mem_list, list)
 439                if (incr->standby)
 440                        add_memory_merged(incr->rn);
 441        add_memory_merged(0);
 442}
 443
 444static void __init insert_increment(u16 rn, int standby, int assigned)
 445{
 446        struct memory_increment *incr, *new_incr;
 447        struct list_head *prev;
 448        u16 last_rn;
 449
 450        new_incr = kzalloc(sizeof(*new_incr), GFP_KERNEL);
 451        if (!new_incr)
 452                return;
 453        new_incr->rn = rn;
 454        new_incr->standby = standby;
 455        last_rn = 0;
 456        prev = &sclp_mem_list;
 457        list_for_each_entry(incr, &sclp_mem_list, list) {
 458                if (assigned && incr->rn > rn)
 459                        break;
 460                if (!assigned && incr->rn - last_rn > 1)
 461                        break;
 462                last_rn = incr->rn;
 463                prev = &incr->list;
 464        }
 465        if (!assigned)
 466                new_incr->rn = last_rn + 1;
 467        if (new_incr->rn > sclp.rnmax) {
 468                kfree(new_incr);
 469                return;
 470        }
 471        list_add(&new_incr->list, prev);
 472}
 473
 474static int sclp_mem_freeze(struct device *dev)
 475{
 476        if (!sclp_mem_state_changed)
 477                return 0;
 478        pr_err("Memory hotplug state changed, suspend refused.\n");
 479        return -EPERM;
 480}
 481
 482struct read_storage_sccb {
 483        struct sccb_header header;
 484        u16 max_id;
 485        u16 assigned;
 486        u16 standby;
 487        u16 :16;
 488        u32 entries[0];
 489} __packed;
 490
 491static const struct dev_pm_ops sclp_mem_pm_ops = {
 492        .freeze         = sclp_mem_freeze,
 493};
 494
 495static struct platform_driver sclp_mem_pdrv = {
 496        .driver = {
 497                .name   = "sclp_mem",
 498                .pm     = &sclp_mem_pm_ops,
 499        },
 500};
 501
 502static int __init sclp_detect_standby_memory(void)
 503{
 504        struct platform_device *sclp_pdev;
 505        struct read_storage_sccb *sccb;
 506        int i, id, assigned, rc;
 507
 508        if (OLDMEM_BASE) /* No standby memory in kdump mode */
 509                return 0;
 510        if ((sclp.facilities & 0xe00000000000ULL) != 0xe00000000000ULL)
 511                return 0;
 512        rc = -ENOMEM;
 513        sccb = (void *) __get_free_page(GFP_KERNEL | GFP_DMA);
 514        if (!sccb)
 515                goto out;
 516        assigned = 0;
 517        for (id = 0; id <= sclp_max_storage_id; id++) {
 518                memset(sccb, 0, PAGE_SIZE);
 519                sccb->header.length = PAGE_SIZE;
 520                rc = sclp_sync_request(0x00040001 | id << 8, sccb);
 521                if (rc)
 522                        goto out;
 523                switch (sccb->header.response_code) {
 524                case 0x0010:
 525                        set_bit(id, sclp_storage_ids);
 526                        for (i = 0; i < sccb->assigned; i++) {
 527                                if (!sccb->entries[i])
 528                                        continue;
 529                                assigned++;
 530                                insert_increment(sccb->entries[i] >> 16, 0, 1);
 531                        }
 532                        break;
 533                case 0x0310:
 534                        break;
 535                case 0x0410:
 536                        for (i = 0; i < sccb->assigned; i++) {
 537                                if (!sccb->entries[i])
 538                                        continue;
 539                                assigned++;
 540                                insert_increment(sccb->entries[i] >> 16, 1, 1);
 541                        }
 542                        break;
 543                default:
 544                        rc = -EIO;
 545                        break;
 546                }
 547                if (!rc)
 548                        sclp_max_storage_id = sccb->max_id;
 549        }
 550        if (rc || list_empty(&sclp_mem_list))
 551                goto out;
 552        for (i = 1; i <= sclp.rnmax - assigned; i++)
 553                insert_increment(0, 1, 0);
 554        rc = register_memory_notifier(&sclp_mem_nb);
 555        if (rc)
 556                goto out;
 557        rc = platform_driver_register(&sclp_mem_pdrv);
 558        if (rc)
 559                goto out;
 560        sclp_pdev = platform_device_register_simple("sclp_mem", -1, NULL, 0);
 561        rc = PTR_ERR_OR_ZERO(sclp_pdev);
 562        if (rc)
 563                goto out_driver;
 564        sclp_add_standby_memory();
 565        goto out;
 566out_driver:
 567        platform_driver_unregister(&sclp_mem_pdrv);
 568out:
 569        free_page((unsigned long) sccb);
 570        return rc;
 571}
 572__initcall(sclp_detect_standby_memory);
 573
 574#endif /* CONFIG_MEMORY_HOTPLUG */
 575
 576/*
 577 * PCI I/O adapter configuration related functions.
 578 */
 579#define SCLP_CMDW_CONFIGURE_PCI                 0x001a0001
 580#define SCLP_CMDW_DECONFIGURE_PCI               0x001b0001
 581
 582#define SCLP_RECONFIG_PCI_ATPYE                 2
 583
 584struct pci_cfg_sccb {
 585        struct sccb_header header;
 586        u8 atype;               /* adapter type */
 587        u8 reserved1;
 588        u16 reserved2;
 589        u32 aid;                /* adapter identifier */
 590} __packed;
 591
 592static int do_pci_configure(sclp_cmdw_t cmd, u32 fid)
 593{
 594        struct pci_cfg_sccb *sccb;
 595        int rc;
 596
 597        if (!SCLP_HAS_PCI_RECONFIG)
 598                return -EOPNOTSUPP;
 599
 600        sccb = (struct pci_cfg_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
 601        if (!sccb)
 602                return -ENOMEM;
 603
 604        sccb->header.length = PAGE_SIZE;
 605        sccb->atype = SCLP_RECONFIG_PCI_ATPYE;
 606        sccb->aid = fid;
 607        rc = sclp_sync_request(cmd, sccb);
 608        if (rc)
 609                goto out;
 610        switch (sccb->header.response_code) {
 611        case 0x0020:
 612        case 0x0120:
 613                break;
 614        default:
 615                pr_warn("configure PCI I/O adapter failed: cmd=0x%08x  response=0x%04x\n",
 616                        cmd, sccb->header.response_code);
 617                rc = -EIO;
 618                break;
 619        }
 620out:
 621        free_page((unsigned long) sccb);
 622        return rc;
 623}
 624
 625int sclp_pci_configure(u32 fid)
 626{
 627        return do_pci_configure(SCLP_CMDW_CONFIGURE_PCI, fid);
 628}
 629EXPORT_SYMBOL(sclp_pci_configure);
 630
 631int sclp_pci_deconfigure(u32 fid)
 632{
 633        return do_pci_configure(SCLP_CMDW_DECONFIGURE_PCI, fid);
 634}
 635EXPORT_SYMBOL(sclp_pci_deconfigure);
 636
 637/*
 638 * Channel path configuration related functions.
 639 */
 640
 641#define SCLP_CMDW_CONFIGURE_CHPATH              0x000f0001
 642#define SCLP_CMDW_DECONFIGURE_CHPATH            0x000e0001
 643#define SCLP_CMDW_READ_CHPATH_INFORMATION       0x00030001
 644
 645struct chp_cfg_sccb {
 646        struct sccb_header header;
 647        u8 ccm;
 648        u8 reserved[6];
 649        u8 cssid;
 650} __attribute__((packed));
 651
 652static int do_chp_configure(sclp_cmdw_t cmd)
 653{
 654        struct chp_cfg_sccb *sccb;
 655        int rc;
 656
 657        if (!SCLP_HAS_CHP_RECONFIG)
 658                return -EOPNOTSUPP;
 659        /* Prepare sccb. */
 660        sccb = (struct chp_cfg_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
 661        if (!sccb)
 662                return -ENOMEM;
 663        sccb->header.length = sizeof(*sccb);
 664        rc = sclp_sync_request(cmd, sccb);
 665        if (rc)
 666                goto out;
 667        switch (sccb->header.response_code) {
 668        case 0x0020:
 669        case 0x0120:
 670        case 0x0440:
 671        case 0x0450:
 672                break;
 673        default:
 674                pr_warning("configure channel-path failed "
 675                           "(cmd=0x%08x, response=0x%04x)\n", cmd,
 676                           sccb->header.response_code);
 677                rc = -EIO;
 678                break;
 679        }
 680out:
 681        free_page((unsigned long) sccb);
 682        return rc;
 683}
 684
 685/**
 686 * sclp_chp_configure - perform configure channel-path sclp command
 687 * @chpid: channel-path ID
 688 *
 689 * Perform configure channel-path command sclp command for specified chpid.
 690 * Return 0 after command successfully finished, non-zero otherwise.
 691 */
 692int sclp_chp_configure(struct chp_id chpid)
 693{
 694        return do_chp_configure(SCLP_CMDW_CONFIGURE_CHPATH | chpid.id << 8);
 695}
 696
 697/**
 698 * sclp_chp_deconfigure - perform deconfigure channel-path sclp command
 699 * @chpid: channel-path ID
 700 *
 701 * Perform deconfigure channel-path command sclp command for specified chpid
 702 * and wait for completion. On success return 0. Return non-zero otherwise.
 703 */
 704int sclp_chp_deconfigure(struct chp_id chpid)
 705{
 706        return do_chp_configure(SCLP_CMDW_DECONFIGURE_CHPATH | chpid.id << 8);
 707}
 708
 709struct chp_info_sccb {
 710        struct sccb_header header;
 711        u8 recognized[SCLP_CHP_INFO_MASK_SIZE];
 712        u8 standby[SCLP_CHP_INFO_MASK_SIZE];
 713        u8 configured[SCLP_CHP_INFO_MASK_SIZE];
 714        u8 ccm;
 715        u8 reserved[6];
 716        u8 cssid;
 717} __attribute__((packed));
 718
 719/**
 720 * sclp_chp_read_info - perform read channel-path information sclp command
 721 * @info: resulting channel-path information data
 722 *
 723 * Perform read channel-path information sclp command and wait for completion.
 724 * On success, store channel-path information in @info and return 0. Return
 725 * non-zero otherwise.
 726 */
 727int sclp_chp_read_info(struct sclp_chp_info *info)
 728{
 729        struct chp_info_sccb *sccb;
 730        int rc;
 731
 732        if (!SCLP_HAS_CHP_INFO)
 733                return -EOPNOTSUPP;
 734        /* Prepare sccb. */
 735        sccb = (struct chp_info_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
 736        if (!sccb)
 737                return -ENOMEM;
 738        sccb->header.length = sizeof(*sccb);
 739        rc = sclp_sync_request(SCLP_CMDW_READ_CHPATH_INFORMATION, sccb);
 740        if (rc)
 741                goto out;
 742        if (sccb->header.response_code != 0x0010) {
 743                pr_warning("read channel-path info failed "
 744                           "(response=0x%04x)\n", sccb->header.response_code);
 745                rc = -EIO;
 746                goto out;
 747        }
 748        memcpy(info->recognized, sccb->recognized, SCLP_CHP_INFO_MASK_SIZE);
 749        memcpy(info->standby, sccb->standby, SCLP_CHP_INFO_MASK_SIZE);
 750        memcpy(info->configured, sccb->configured, SCLP_CHP_INFO_MASK_SIZE);
 751out:
 752        free_page((unsigned long) sccb);
 753        return rc;
 754}
 755