108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens/* 2039979049834bde56f67f8078c802b416bd4763cGerald Schaefer * Copyright IBM Corp. 2007, 2009 308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens * 4039979049834bde56f67f8078c802b416bd4763cGerald Schaefer * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>, 5039979049834bde56f67f8078c802b416bd4763cGerald Schaefer * Peter Oberparleiter <peter.oberparleiter@de.ibm.com> 608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens */ 708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 8b3ff088b3025c3583194edd7576215b61333111fMartin Schwidefsky#define KMSG_COMPONENT "sclp_cmd" 9b3ff088b3025c3583194edd7576215b61333111fMartin Schwidefsky#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 10b3ff088b3025c3583194edd7576215b61333111fMartin Schwidefsky 1108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens#include <linux/completion.h> 1208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens#include <linux/init.h> 1308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens#include <linux/errno.h> 14039979049834bde56f67f8078c802b416bd4763cGerald Schaefer#include <linux/err.h> 1508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens#include <linux/slab.h> 1608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens#include <linux/string.h> 17e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens#include <linux/mm.h> 18e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens#include <linux/mmzone.h> 19e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens#include <linux/memory.h> 20039979049834bde56f67f8078c802b416bd4763cGerald Schaefer#include <linux/platform_device.h> 214b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens#include <asm/chpid.h> 2208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens#include <asm/sclp.h> 2323d75d9cadd79bc9fd6553857d57c679cf18d4cbHeiko Carstens#include <asm/setup.h> 24a0616cdebcfd575dcd4c46102d1b52fbb827fc29David Howells#include <asm/ctl_reg.h> 2508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 26b3ff088b3025c3583194edd7576215b61333111fMartin Schwidefsky#include "sclp.h" 2708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 2808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens#define SCLP_CMDW_READ_SCP_INFO 0x00020001 2908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001 3008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 3108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensstruct read_info_sccb { 3208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens struct sccb_header header; /* 0-7 */ 3308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u16 rnmax; /* 8-9 */ 3408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u8 rnsize; /* 10 */ 3508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u8 _reserved0[24 - 11]; /* 11-15 */ 3608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u8 loadparm[8]; /* 24-31 */ 3708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u8 _reserved1[48 - 32]; /* 32-47 */ 3808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u64 facilities; /* 48-55 */ 3908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u8 _reserved2[84 - 56]; /* 56-83 */ 4008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u8 fac84; /* 84 */ 4108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u8 _reserved3[91 - 85]; /* 85-90 */ 4208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u8 flags; /* 91 */ 4308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u8 _reserved4[100 - 92]; /* 92-99 */ 4408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u32 rnsize2; /* 100-103 */ 4508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u64 rnmax2; /* 104-111 */ 4608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u8 _reserved5[4096 - 112]; /* 112-4095 */ 4708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens} __attribute__((packed, aligned(PAGE_SIZE))); 4808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 4908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensstatic struct read_info_sccb __initdata early_read_info_sccb; 5008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensstatic int __initdata early_read_info_sccb_valid; 5108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 5208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensu64 sclp_facilities; 5308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensstatic u8 sclp_fac84; 54e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstatic unsigned long long rzm; 55e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstatic unsigned long long rnmax; 5608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 5708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensstatic int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb) 5808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens{ 5908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens int rc; 6008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 6108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens __ctl_set_bit(0, 9); 6208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens rc = sclp_service_call(cmd, sccb); 6308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens if (rc) 6408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens goto out; 65b50511e41aa51a89b4176784a670582424bc7db6Martin Schwidefsky __load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | 66b50511e41aa51a89b4176784a670582424bc7db6Martin Schwidefsky PSW_MASK_BA | PSW_MASK_EXT | PSW_MASK_WAIT); 6708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens local_irq_disable(); 6808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensout: 6908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens /* Contents of the sccb might have changed. */ 7008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens barrier(); 7108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens __ctl_clear_bit(0, 9); 7208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens return rc; 7308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens} 7408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 7523d1742179170b69e61ac9166248ffd64857e55aHeiko Carstensstatic void __init sclp_read_info_early(void) 7608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens{ 7708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens int rc; 7808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens int i; 7908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens struct read_info_sccb *sccb; 8008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, 8108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens SCLP_CMDW_READ_SCP_INFO}; 8208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 8308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens sccb = &early_read_info_sccb; 8408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens for (i = 0; i < ARRAY_SIZE(commands); i++) { 8508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens do { 8608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens memset(sccb, 0, sizeof(*sccb)); 8708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens sccb->header.length = sizeof(*sccb); 88cb9d71604a6e3d6aa93bb663747a62fc520da483Martin Schwidefsky sccb->header.function_code = 0x80; 8908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens sccb->header.control_mask[2] = 0x80; 9008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens rc = sclp_cmd_sync_early(commands[i], sccb); 9108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens } while (rc == -EBUSY); 9208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 9308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens if (rc) 9408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens break; 9508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens if (sccb->header.response_code == 0x10) { 9608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens early_read_info_sccb_valid = 1; 9708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens break; 9808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens } 9908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens if (sccb->header.response_code != 0x1f0) 10008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens break; 10108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens } 10208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens} 10308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 10408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensvoid __init sclp_facilities_detect(void) 10508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens{ 10608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens struct read_info_sccb *sccb; 10708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 10823d1742179170b69e61ac9166248ffd64857e55aHeiko Carstens sclp_read_info_early(); 10908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens if (!early_read_info_sccb_valid) 11023d1742179170b69e61ac9166248ffd64857e55aHeiko Carstens return; 11123d1742179170b69e61ac9166248ffd64857e55aHeiko Carstens 11208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens sccb = &early_read_info_sccb; 11323d1742179170b69e61ac9166248ffd64857e55aHeiko Carstens sclp_facilities = sccb->facilities; 11423d1742179170b69e61ac9166248ffd64857e55aHeiko Carstens sclp_fac84 = sccb->fac84; 115e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; 116e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; 117e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens rzm <<= 20; 11823d1742179170b69e61ac9166248ffd64857e55aHeiko Carstens} 11923d1742179170b69e61ac9166248ffd64857e55aHeiko Carstens 12023d1742179170b69e61ac9166248ffd64857e55aHeiko Carstensunsigned long long sclp_get_rnmax(void) 12123d1742179170b69e61ac9166248ffd64857e55aHeiko Carstens{ 12223d1742179170b69e61ac9166248ffd64857e55aHeiko Carstens return rnmax; 12323d1742179170b69e61ac9166248ffd64857e55aHeiko Carstens} 12423d1742179170b69e61ac9166248ffd64857e55aHeiko Carstens 12523d1742179170b69e61ac9166248ffd64857e55aHeiko Carstensunsigned long long sclp_get_rzm(void) 12623d1742179170b69e61ac9166248ffd64857e55aHeiko Carstens{ 12723d1742179170b69e61ac9166248ffd64857e55aHeiko Carstens return rzm; 12808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens} 12908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 13008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens/* 13123d1742179170b69e61ac9166248ffd64857e55aHeiko Carstens * This function will be called after sclp_facilities_detect(), which gets 13223d1742179170b69e61ac9166248ffd64857e55aHeiko Carstens * called from early.c code. Therefore the sccb should have valid contents. 13308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens */ 13408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensvoid __init sclp_get_ipl_info(struct sclp_ipl_info *info) 13508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens{ 13608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens struct read_info_sccb *sccb; 13708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 13808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens if (!early_read_info_sccb_valid) 13908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens return; 14008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens sccb = &early_read_info_sccb; 14108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens info->is_valid = 1; 14208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens if (sccb->flags & 0x2) 14308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens info->has_dump = 1; 14408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN); 14508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens} 14608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 14708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensstatic void sclp_sync_callback(struct sclp_req *req, void *data) 14808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens{ 14908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens struct completion *completion = data; 15008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 15108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens complete(completion); 15208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens} 15308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 15408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensstatic int do_sync_request(sclp_cmdw_t cmd, void *sccb) 15508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens{ 15608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens struct completion completion; 15708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens struct sclp_req *request; 15808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens int rc; 15908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 16008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens request = kzalloc(sizeof(*request), GFP_KERNEL); 16108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens if (!request) 16208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens return -ENOMEM; 16308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens request->command = cmd; 16408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens request->sccb = sccb; 16508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens request->status = SCLP_REQ_FILLED; 16608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens request->callback = sclp_sync_callback; 16708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens request->callback_data = &completion; 16808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens init_completion(&completion); 16908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 17008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens /* Perform sclp request. */ 17108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens rc = sclp_add_request(request); 17208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens if (rc) 17308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens goto out; 17408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens wait_for_completion(&completion); 17508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 17608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens /* Check response. */ 17708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens if (request->status != SCLP_REQ_DONE) { 178b3ff088b3025c3583194edd7576215b61333111fMartin Schwidefsky pr_warning("sync request failed (cmd=0x%08x, " 179b3ff088b3025c3583194edd7576215b61333111fMartin Schwidefsky "status=0x%02x)\n", cmd, request->status); 18008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens rc = -EIO; 18108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens } 18208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensout: 18308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens kfree(request); 18408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens return rc; 18508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens} 18608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 18708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens/* 18808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens * CPU configuration related functions. 18908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens */ 19008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 19108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens#define SCLP_CMDW_READ_CPU_INFO 0x00010001 19208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens#define SCLP_CMDW_CONFIGURE_CPU 0x00110001 19308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens#define SCLP_CMDW_DECONFIGURE_CPU 0x00100001 19408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 19508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensstruct read_cpu_info_sccb { 19608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens struct sccb_header header; 19708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u16 nr_configured; 19808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u16 offset_configured; 19908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u16 nr_standby; 20008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u16 offset_standby; 20108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens u8 reserved[4096 - 16]; 20208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens} __attribute__((packed, aligned(PAGE_SIZE))); 20308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 20408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensstatic void sclp_fill_cpu_info(struct sclp_cpu_info *info, 20508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens struct read_cpu_info_sccb *sccb) 20608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens{ 20708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens char *page = (char *) sccb; 20808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 20908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens memset(info, 0, sizeof(*info)); 21008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens info->configured = sccb->nr_configured; 21108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens info->standby = sccb->nr_standby; 21208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens info->combined = sccb->nr_configured + sccb->nr_standby; 21308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens info->has_cpu_type = sclp_fac84 & 0x1; 21408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens memcpy(&info->cpu, page + sccb->offset_configured, 21508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens info->combined * sizeof(struct sclp_cpu_entry)); 21608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens} 21708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 21848483b3290988952a593c6e66ca354c19f1a4350Heiko Carstensint sclp_get_cpu_info(struct sclp_cpu_info *info) 21908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens{ 22008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens int rc; 22108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens struct read_cpu_info_sccb *sccb; 22208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 22308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens if (!SCLP_HAS_CPU_INFO) 22408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens return -EOPNOTSUPP; 22548483b3290988952a593c6e66ca354c19f1a4350Heiko Carstens sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); 22608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens if (!sccb) 22708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens return -ENOMEM; 22808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens sccb->header.length = sizeof(*sccb); 22908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens rc = do_sync_request(SCLP_CMDW_READ_CPU_INFO, sccb); 23008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens if (rc) 23108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens goto out; 23208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens if (sccb->header.response_code != 0x0010) { 233b3ff088b3025c3583194edd7576215b61333111fMartin Schwidefsky pr_warning("readcpuinfo failed (response=0x%04x)\n", 234b3ff088b3025c3583194edd7576215b61333111fMartin Schwidefsky sccb->header.response_code); 23508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens rc = -EIO; 23608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens goto out; 23708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens } 23808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens sclp_fill_cpu_info(info, sccb); 23908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensout: 24008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens free_page((unsigned long) sccb); 24108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens return rc; 24208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens} 24308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 24408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensstruct cpu_configure_sccb { 24508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens struct sccb_header header; 24608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens} __attribute__((packed, aligned(8))); 24708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 24808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensstatic int do_cpu_configure(sclp_cmdw_t cmd) 24908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens{ 25008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens struct cpu_configure_sccb *sccb; 25108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens int rc; 25208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 25308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens if (!SCLP_HAS_CPU_RECONFIG) 25408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens return -EOPNOTSUPP; 25508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens /* 25608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens * This is not going to cross a page boundary since we force 25708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens * kmalloc to have a minimum alignment of 8 bytes on s390. 25808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens */ 25908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens sccb = kzalloc(sizeof(*sccb), GFP_KERNEL | GFP_DMA); 26008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens if (!sccb) 26108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens return -ENOMEM; 26208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens sccb->header.length = sizeof(*sccb); 26308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens rc = do_sync_request(cmd, sccb); 26408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens if (rc) 26508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens goto out; 26608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens switch (sccb->header.response_code) { 26708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens case 0x0020: 26808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens case 0x0120: 26908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens break; 27008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens default: 271b3ff088b3025c3583194edd7576215b61333111fMartin Schwidefsky pr_warning("configure cpu failed (cmd=0x%08x, " 272b3ff088b3025c3583194edd7576215b61333111fMartin Schwidefsky "response=0x%04x)\n", cmd, 273b3ff088b3025c3583194edd7576215b61333111fMartin Schwidefsky sccb->header.response_code); 27408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens rc = -EIO; 27508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens break; 27608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens } 27708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensout: 27808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens kfree(sccb); 27908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens return rc; 28008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens} 28108d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 28208d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensint sclp_cpu_configure(u8 cpu) 28308d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens{ 28408d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens return do_cpu_configure(SCLP_CMDW_CONFIGURE_CPU | cpu << 8); 28508d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens} 28608d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens 28708d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstensint sclp_cpu_deconfigure(u8 cpu) 28808d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens{ 28908d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens return do_cpu_configure(SCLP_CMDW_DECONFIGURE_CPU | cpu << 8); 29008d07968277cd898c88bf12b7720d89c02c4f139Heiko Carstens} 2914b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens 292e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens#ifdef CONFIG_MEMORY_HOTPLUG 293e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 294e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstatic DEFINE_MUTEX(sclp_mem_mutex); 295e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstatic LIST_HEAD(sclp_mem_list); 296e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstatic u8 sclp_max_storage_id; 297e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstatic unsigned long sclp_storage_ids[256 / BITS_PER_LONG]; 298039979049834bde56f67f8078c802b416bd4763cGerald Schaeferstatic int sclp_mem_state_changed; 299e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 300e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstruct memory_increment { 301e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens struct list_head list; 302e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens u16 rn; 303e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens int standby; 304e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens int usecount; 305e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens}; 306e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 307e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstruct assign_storage_sccb { 308e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens struct sccb_header header; 309e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens u16 rn; 310e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens} __packed; 311e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 3129c95258c0d5911ae263bf50d854e402ce973ab32Heiko Carstensint arch_get_memory_phys_device(unsigned long start_pfn) 3139c95258c0d5911ae263bf50d854e402ce973ab32Heiko Carstens{ 3149c95258c0d5911ae263bf50d854e402ce973ab32Heiko Carstens if (!rzm) 3159c95258c0d5911ae263bf50d854e402ce973ab32Heiko Carstens return 0; 3169c95258c0d5911ae263bf50d854e402ce973ab32Heiko Carstens return PFN_PHYS(start_pfn) >> ilog2(rzm); 3179c95258c0d5911ae263bf50d854e402ce973ab32Heiko Carstens} 3189c95258c0d5911ae263bf50d854e402ce973ab32Heiko Carstens 319e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstatic unsigned long long rn2addr(u16 rn) 320e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens{ 321e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens return (unsigned long long) (rn - 1) * rzm; 322e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens} 323e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 324e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstatic int do_assign_storage(sclp_cmdw_t cmd, u16 rn) 325e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens{ 326e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens struct assign_storage_sccb *sccb; 327e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens int rc; 328e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 329e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); 330e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (!sccb) 331e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens return -ENOMEM; 332e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens sccb->header.length = PAGE_SIZE; 333e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens sccb->rn = rn; 334e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens rc = do_sync_request(cmd, sccb); 335e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (rc) 336e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens goto out; 337e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens switch (sccb->header.response_code) { 338e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens case 0x0020: 339e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens case 0x0120: 340e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens break; 341e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens default: 342675be97a32a5f12650b86391b7431f1e10811f1eHeiko Carstens pr_warning("assign storage failed (cmd=0x%08x, " 343675be97a32a5f12650b86391b7431f1e10811f1eHeiko Carstens "response=0x%04x, rn=0x%04x)\n", cmd, 344675be97a32a5f12650b86391b7431f1e10811f1eHeiko Carstens sccb->header.response_code, rn); 345e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens rc = -EIO; 346e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens break; 347e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens } 348e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensout: 349e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens free_page((unsigned long) sccb); 350e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens return rc; 351e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens} 352e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 353e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstatic int sclp_assign_storage(u16 rn) 354e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens{ 355e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens return do_assign_storage(0x000d0001, rn); 356e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens} 357e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 358e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstatic int sclp_unassign_storage(u16 rn) 359e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens{ 360e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens return do_assign_storage(0x000c0001, rn); 361e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens} 362e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 363e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstruct attach_storage_sccb { 364e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens struct sccb_header header; 365e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens u16 :16; 366e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens u16 assigned; 367e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens u32 :32; 368e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens u32 entries[0]; 369e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens} __packed; 370e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 371e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstatic int sclp_attach_storage(u8 id) 372e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens{ 373e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens struct attach_storage_sccb *sccb; 374e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens int rc; 375e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens int i; 376e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 377e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); 378e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (!sccb) 379e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens return -ENOMEM; 380e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens sccb->header.length = PAGE_SIZE; 381e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens rc = do_sync_request(0x00080001 | id << 8, sccb); 382e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (rc) 383e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens goto out; 384e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens switch (sccb->header.response_code) { 385e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens case 0x0020: 386e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens set_bit(id, sclp_storage_ids); 3878adb4ca344b48bbbf87ca66fd07a2dd503619714Heiko Carstens for (i = 0; i < sccb->assigned; i++) { 3888adb4ca344b48bbbf87ca66fd07a2dd503619714Heiko Carstens if (sccb->entries[i]) 3898adb4ca344b48bbbf87ca66fd07a2dd503619714Heiko Carstens sclp_unassign_storage(sccb->entries[i] >> 16); 3908adb4ca344b48bbbf87ca66fd07a2dd503619714Heiko Carstens } 391e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens break; 392e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens default: 393e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens rc = -EIO; 394e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens break; 395e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens } 396e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensout: 397e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens free_page((unsigned long) sccb); 398e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens return rc; 399e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens} 400e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 401e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstatic int sclp_mem_change_state(unsigned long start, unsigned long size, 402e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens int online) 403e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens{ 404e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens struct memory_increment *incr; 405e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens unsigned long long istart; 406e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens int rc = 0; 407e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 408e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens list_for_each_entry(incr, &sclp_mem_list, list) { 409e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens istart = rn2addr(incr->rn); 410e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (start + size - 1 < istart) 411e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens break; 412e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (start > istart + rzm - 1) 413e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens continue; 414e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (online) { 415e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (incr->usecount++) 416e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens continue; 417e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens /* 418e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens * Don't break the loop if one assign fails. Loop may 419e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens * be walked again on CANCEL and we can't save 420e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens * information if state changed before or not. 421e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens * So continue and increase usecount for all increments. 422e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens */ 423e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens rc |= sclp_assign_storage(incr->rn); 424e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens } else { 425e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (--incr->usecount) 426e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens continue; 427e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens sclp_unassign_storage(incr->rn); 428e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens } 429e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens } 430e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens return rc ? -EIO : 0; 431e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens} 432e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 433e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstatic int sclp_mem_notifier(struct notifier_block *nb, 434e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens unsigned long action, void *data) 435e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens{ 436e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens unsigned long start, size; 437e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens struct memory_notify *arg; 438e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens unsigned char id; 439e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens int rc = 0; 440e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 441e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens arg = data; 442e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens start = arg->start_pfn << PAGE_SHIFT; 443e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens size = arg->nr_pages << PAGE_SHIFT; 444e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens mutex_lock(&sclp_mem_mutex); 445fc89db4b789fc9edf88440f6896f04a879ed3b46Akinobu Mita for_each_clear_bit(id, sclp_storage_ids, sclp_max_storage_id + 1) 446fc89db4b789fc9edf88440f6896f04a879ed3b46Akinobu Mita sclp_attach_storage(id); 447e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens switch (action) { 448e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens case MEM_ONLINE: 4497e9238fbc10373effc2c3b0b516b0bdc8fefc27bGerald Schaefer case MEM_GOING_OFFLINE: 4507e9238fbc10373effc2c3b0b516b0bdc8fefc27bGerald Schaefer case MEM_CANCEL_OFFLINE: 451e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens break; 452e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens case MEM_GOING_ONLINE: 453e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens rc = sclp_mem_change_state(start, size, 1); 454e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens break; 455e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens case MEM_CANCEL_ONLINE: 456e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens sclp_mem_change_state(start, size, 0); 457e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens break; 4587e9238fbc10373effc2c3b0b516b0bdc8fefc27bGerald Schaefer case MEM_OFFLINE: 4597e9238fbc10373effc2c3b0b516b0bdc8fefc27bGerald Schaefer sclp_mem_change_state(start, size, 0); 4607e9238fbc10373effc2c3b0b516b0bdc8fefc27bGerald Schaefer break; 461e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens default: 462e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens rc = -EINVAL; 463e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens break; 464e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens } 465039979049834bde56f67f8078c802b416bd4763cGerald Schaefer if (!rc) 466039979049834bde56f67f8078c802b416bd4763cGerald Schaefer sclp_mem_state_changed = 1; 467e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens mutex_unlock(&sclp_mem_mutex); 468e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens return rc ? NOTIFY_BAD : NOTIFY_OK; 469e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens} 470e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 471e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstatic struct notifier_block sclp_mem_nb = { 472e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens .notifier_call = sclp_mem_notifier, 473e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens}; 474e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 475e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstatic void __init add_memory_merged(u16 rn) 476e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens{ 477e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens static u16 first_rn, num; 478e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens unsigned long long start, size; 479e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 480e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (rn && first_rn && (first_rn + num == rn)) { 481e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens num++; 482e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens return; 483e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens } 484e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (!first_rn) 485e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens goto skip_add; 486e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens start = rn2addr(first_rn); 487e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens size = (unsigned long long ) num * rzm; 488e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (start >= VMEM_MAX_PHYS) 489e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens goto skip_add; 490e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (start + size > VMEM_MAX_PHYS) 491e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens size = VMEM_MAX_PHYS - start; 49223d75d9cadd79bc9fd6553857d57c679cf18d4cbHeiko Carstens if (memory_end_set && (start >= memory_end)) 49323d75d9cadd79bc9fd6553857d57c679cf18d4cbHeiko Carstens goto skip_add; 49423d75d9cadd79bc9fd6553857d57c679cf18d4cbHeiko Carstens if (memory_end_set && (start + size > memory_end)) 49523d75d9cadd79bc9fd6553857d57c679cf18d4cbHeiko Carstens size = memory_end - start; 496e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens add_memory(0, start, size); 497e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensskip_add: 498e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens first_rn = rn; 499e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens num = 1; 500e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens} 501e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 502e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstatic void __init sclp_add_standby_memory(void) 503e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens{ 504e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens struct memory_increment *incr; 505e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 506e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens list_for_each_entry(incr, &sclp_mem_list, list) 507e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (incr->standby) 508e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens add_memory_merged(incr->rn); 509e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens add_memory_merged(0); 510e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens} 511e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 512e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstatic void __init insert_increment(u16 rn, int standby, int assigned) 513e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens{ 514e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens struct memory_increment *incr, *new_incr; 515e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens struct list_head *prev; 516e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens u16 last_rn; 517e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 518e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens new_incr = kzalloc(sizeof(*new_incr), GFP_KERNEL); 519e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (!new_incr) 520e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens return; 521e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens new_incr->rn = rn; 522e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens new_incr->standby = standby; 523fdb1bb157525907163e2a0c96fe8bb19fbe867a8Heiko Carstens if (!standby) 524fdb1bb157525907163e2a0c96fe8bb19fbe867a8Heiko Carstens new_incr->usecount = 1; 525e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens last_rn = 0; 526e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens prev = &sclp_mem_list; 527e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens list_for_each_entry(incr, &sclp_mem_list, list) { 528e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (assigned && incr->rn > rn) 529e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens break; 530e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (!assigned && incr->rn - last_rn > 1) 531e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens break; 532e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens last_rn = incr->rn; 533e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens prev = &incr->list; 534e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens } 535e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (!assigned) 536e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens new_incr->rn = last_rn + 1; 537e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (new_incr->rn > rnmax) { 538e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens kfree(new_incr); 539e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens return; 540e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens } 541e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens list_add(&new_incr->list, prev); 542e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens} 543e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 544039979049834bde56f67f8078c802b416bd4763cGerald Schaeferstatic int sclp_mem_freeze(struct device *dev) 545039979049834bde56f67f8078c802b416bd4763cGerald Schaefer{ 546039979049834bde56f67f8078c802b416bd4763cGerald Schaefer if (!sclp_mem_state_changed) 547039979049834bde56f67f8078c802b416bd4763cGerald Schaefer return 0; 548039979049834bde56f67f8078c802b416bd4763cGerald Schaefer pr_err("Memory hotplug state changed, suspend refused.\n"); 549039979049834bde56f67f8078c802b416bd4763cGerald Schaefer return -EPERM; 550039979049834bde56f67f8078c802b416bd4763cGerald Schaefer} 551039979049834bde56f67f8078c802b416bd4763cGerald Schaefer 552e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstruct read_storage_sccb { 553e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens struct sccb_header header; 554e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens u16 max_id; 555e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens u16 assigned; 556e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens u16 standby; 557e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens u16 :16; 558e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens u32 entries[0]; 559e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens} __packed; 560e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 561471452104b8520337ae2fb48c4e61cd4896e025dAlexey Dobriyanstatic const struct dev_pm_ops sclp_mem_pm_ops = { 562039979049834bde56f67f8078c802b416bd4763cGerald Schaefer .freeze = sclp_mem_freeze, 563039979049834bde56f67f8078c802b416bd4763cGerald Schaefer}; 564039979049834bde56f67f8078c802b416bd4763cGerald Schaefer 565039979049834bde56f67f8078c802b416bd4763cGerald Schaeferstatic struct platform_driver sclp_mem_pdrv = { 566039979049834bde56f67f8078c802b416bd4763cGerald Schaefer .driver = { 567039979049834bde56f67f8078c802b416bd4763cGerald Schaefer .name = "sclp_mem", 568039979049834bde56f67f8078c802b416bd4763cGerald Schaefer .pm = &sclp_mem_pm_ops, 569039979049834bde56f67f8078c802b416bd4763cGerald Schaefer }, 570039979049834bde56f67f8078c802b416bd4763cGerald Schaefer}; 571039979049834bde56f67f8078c802b416bd4763cGerald Schaefer 572e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensstatic int __init sclp_detect_standby_memory(void) 573e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens{ 574039979049834bde56f67f8078c802b416bd4763cGerald Schaefer struct platform_device *sclp_pdev; 575e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens struct read_storage_sccb *sccb; 576e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens int i, id, assigned, rc; 577e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 578e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (!early_read_info_sccb_valid) 579e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens return 0; 580e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if ((sclp_facilities & 0xe00000000000ULL) != 0xe00000000000ULL) 581e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens return 0; 582e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens rc = -ENOMEM; 583e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens sccb = (void *) __get_free_page(GFP_KERNEL | GFP_DMA); 584e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (!sccb) 585e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens goto out; 586e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens assigned = 0; 587e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens for (id = 0; id <= sclp_max_storage_id; id++) { 588e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens memset(sccb, 0, PAGE_SIZE); 589e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens sccb->header.length = PAGE_SIZE; 590e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens rc = do_sync_request(0x00040001 | id << 8, sccb); 591e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (rc) 592e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens goto out; 593e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens switch (sccb->header.response_code) { 594e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens case 0x0010: 595e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens set_bit(id, sclp_storage_ids); 596e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens for (i = 0; i < sccb->assigned; i++) { 597e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (!sccb->entries[i]) 598e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens continue; 599e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens assigned++; 600e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens insert_increment(sccb->entries[i] >> 16, 0, 1); 601e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens } 602e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens break; 603e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens case 0x0310: 604e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens break; 605e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens case 0x0410: 606e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens for (i = 0; i < sccb->assigned; i++) { 607e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (!sccb->entries[i]) 608e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens continue; 609e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens assigned++; 610e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens insert_increment(sccb->entries[i] >> 16, 1, 1); 611e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens } 612e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens break; 613e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens default: 614e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens rc = -EIO; 615e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens break; 616e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens } 617e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (!rc) 618e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens sclp_max_storage_id = sccb->max_id; 619e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens } 620e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (rc || list_empty(&sclp_mem_list)) 621e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens goto out; 622e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens for (i = 1; i <= rnmax - assigned; i++) 623e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens insert_increment(0, 1, 0); 624e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens rc = register_memory_notifier(&sclp_mem_nb); 625e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens if (rc) 626e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens goto out; 627039979049834bde56f67f8078c802b416bd4763cGerald Schaefer rc = platform_driver_register(&sclp_mem_pdrv); 628039979049834bde56f67f8078c802b416bd4763cGerald Schaefer if (rc) 629039979049834bde56f67f8078c802b416bd4763cGerald Schaefer goto out; 630039979049834bde56f67f8078c802b416bd4763cGerald Schaefer sclp_pdev = platform_device_register_simple("sclp_mem", -1, NULL, 0); 631039979049834bde56f67f8078c802b416bd4763cGerald Schaefer rc = IS_ERR(sclp_pdev) ? PTR_ERR(sclp_pdev) : 0; 632039979049834bde56f67f8078c802b416bd4763cGerald Schaefer if (rc) 633039979049834bde56f67f8078c802b416bd4763cGerald Schaefer goto out_driver; 634e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens sclp_add_standby_memory(); 635039979049834bde56f67f8078c802b416bd4763cGerald Schaefer goto out; 636039979049834bde56f67f8078c802b416bd4763cGerald Schaeferout_driver: 637039979049834bde56f67f8078c802b416bd4763cGerald Schaefer platform_driver_unregister(&sclp_mem_pdrv); 638e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstensout: 639e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens free_page((unsigned long) sccb); 640e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens return rc; 641e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens} 642e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens__initcall(sclp_detect_standby_memory); 643e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 644e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens#endif /* CONFIG_MEMORY_HOTPLUG */ 645e0bc24958e1305efe176adc9d5f23a09e84c0058Heiko Carstens 6464b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens/* 6474b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens * Channel path configuration related functions. 6484b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens */ 6494b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens 6504b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens#define SCLP_CMDW_CONFIGURE_CHPATH 0x000f0001 6514b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens#define SCLP_CMDW_DECONFIGURE_CHPATH 0x000e0001 6524b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens#define SCLP_CMDW_READ_CHPATH_INFORMATION 0x00030001 6534b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens 6544b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstensstruct chp_cfg_sccb { 6554b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens struct sccb_header header; 6564b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens u8 ccm; 6574b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens u8 reserved[6]; 6584b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens u8 cssid; 6594b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens} __attribute__((packed)); 6604b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens 6614b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstensstatic int do_chp_configure(sclp_cmdw_t cmd) 6624b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens{ 6634b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens struct chp_cfg_sccb *sccb; 6644b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens int rc; 6654b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens 6664b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens if (!SCLP_HAS_CHP_RECONFIG) 6674b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens return -EOPNOTSUPP; 6684b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens /* Prepare sccb. */ 6694b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens sccb = (struct chp_cfg_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA); 6704b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens if (!sccb) 6714b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens return -ENOMEM; 6724b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens sccb->header.length = sizeof(*sccb); 6734b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens rc = do_sync_request(cmd, sccb); 6744b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens if (rc) 6754b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens goto out; 6764b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens switch (sccb->header.response_code) { 6774b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens case 0x0020: 6784b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens case 0x0120: 6794b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens case 0x0440: 6804b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens case 0x0450: 6814b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens break; 6824b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens default: 683b3ff088b3025c3583194edd7576215b61333111fMartin Schwidefsky pr_warning("configure channel-path failed " 684b3ff088b3025c3583194edd7576215b61333111fMartin Schwidefsky "(cmd=0x%08x, response=0x%04x)\n", cmd, 685b3ff088b3025c3583194edd7576215b61333111fMartin Schwidefsky sccb->header.response_code); 6864b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens rc = -EIO; 6874b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens break; 6884b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens } 6894b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstensout: 6904b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens free_page((unsigned long) sccb); 6914b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens return rc; 6924b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens} 6934b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens 6944b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens/** 6954b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens * sclp_chp_configure - perform configure channel-path sclp command 6964b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens * @chpid: channel-path ID 6974b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens * 6984b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens * Perform configure channel-path command sclp command for specified chpid. 6994b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens * Return 0 after command successfully finished, non-zero otherwise. 7004b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens */ 7014b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstensint sclp_chp_configure(struct chp_id chpid) 7024b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens{ 7034b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens return do_chp_configure(SCLP_CMDW_CONFIGURE_CHPATH | chpid.id << 8); 7044b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens} 7054b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens 7064b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens/** 7074b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens * sclp_chp_deconfigure - perform deconfigure channel-path sclp command 7084b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens * @chpid: channel-path ID 7094b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens * 7104b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens * Perform deconfigure channel-path command sclp command for specified chpid 7114b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens * and wait for completion. On success return 0. Return non-zero otherwise. 7124b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens */ 7134b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstensint sclp_chp_deconfigure(struct chp_id chpid) 7144b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens{ 7154b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens return do_chp_configure(SCLP_CMDW_DECONFIGURE_CHPATH | chpid.id << 8); 7164b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens} 7174b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens 7184b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstensstruct chp_info_sccb { 7194b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens struct sccb_header header; 7204b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens u8 recognized[SCLP_CHP_INFO_MASK_SIZE]; 7214b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens u8 standby[SCLP_CHP_INFO_MASK_SIZE]; 7224b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens u8 configured[SCLP_CHP_INFO_MASK_SIZE]; 7234b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens u8 ccm; 7244b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens u8 reserved[6]; 7254b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens u8 cssid; 7264b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens} __attribute__((packed)); 7274b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens 7284b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens/** 7294b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens * sclp_chp_read_info - perform read channel-path information sclp command 7304b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens * @info: resulting channel-path information data 7314b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens * 7324b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens * Perform read channel-path information sclp command and wait for completion. 7334b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens * On success, store channel-path information in @info and return 0. Return 7344b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens * non-zero otherwise. 7354b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens */ 7364b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstensint sclp_chp_read_info(struct sclp_chp_info *info) 7374b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens{ 7384b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens struct chp_info_sccb *sccb; 7394b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens int rc; 7404b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens 7414b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens if (!SCLP_HAS_CHP_INFO) 7424b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens return -EOPNOTSUPP; 7434b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens /* Prepare sccb. */ 7444b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens sccb = (struct chp_info_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA); 7454b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens if (!sccb) 7464b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens return -ENOMEM; 7474b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens sccb->header.length = sizeof(*sccb); 7484b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens rc = do_sync_request(SCLP_CMDW_READ_CHPATH_INFORMATION, sccb); 7494b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens if (rc) 7504b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens goto out; 7514b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens if (sccb->header.response_code != 0x0010) { 752b3ff088b3025c3583194edd7576215b61333111fMartin Schwidefsky pr_warning("read channel-path info failed " 753b3ff088b3025c3583194edd7576215b61333111fMartin Schwidefsky "(response=0x%04x)\n", sccb->header.response_code); 7544b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens rc = -EIO; 7554b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens goto out; 7564b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens } 7574b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens memcpy(info->recognized, sccb->recognized, SCLP_CHP_INFO_MASK_SIZE); 7584b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens memcpy(info->standby, sccb->standby, SCLP_CHP_INFO_MASK_SIZE); 7594b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens memcpy(info->configured, sccb->configured, SCLP_CHP_INFO_MASK_SIZE); 7604b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstensout: 7614b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens free_page((unsigned long) sccb); 7624b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens return rc; 7634b28a8fe78bd593cdc4454cf28af71ca9556914dHeiko Carstens} 764