root/arch/powerpc/platforms/pseries/mobility.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mobility_rtas_call
  2. delete_dt_node
  3. update_dt_property
  4. update_dt_node
  5. add_dt_node
  6. prrn_update_node
  7. pseries_devicetree_update
  8. post_mobility_fixup
  9. migration_store
  10. mobility_sysfs_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Support for Partition Mobility/Migration
   4  *
   5  * Copyright (C) 2010 Nathan Fontenot
   6  * Copyright (C) 2010 IBM Corporation
   7  */
   8 
   9 #include <linux/cpu.h>
  10 #include <linux/kernel.h>
  11 #include <linux/kobject.h>
  12 #include <linux/sched.h>
  13 #include <linux/smp.h>
  14 #include <linux/stat.h>
  15 #include <linux/completion.h>
  16 #include <linux/device.h>
  17 #include <linux/delay.h>
  18 #include <linux/slab.h>
  19 #include <linux/stringify.h>
  20 
  21 #include <asm/machdep.h>
  22 #include <asm/rtas.h>
  23 #include "pseries.h"
  24 #include "../../kernel/cacheinfo.h"
  25 
  26 static struct kobject *mobility_kobj;
  27 
  28 struct update_props_workarea {
  29         __be32 phandle;
  30         __be32 state;
  31         __be64 reserved;
  32         __be32 nprops;
  33 } __packed;
  34 
  35 #define NODE_ACTION_MASK        0xff000000
  36 #define NODE_COUNT_MASK         0x00ffffff
  37 
  38 #define DELETE_DT_NODE  0x01000000
  39 #define UPDATE_DT_NODE  0x02000000
  40 #define ADD_DT_NODE     0x03000000
  41 
  42 #define MIGRATION_SCOPE (1)
  43 #define PRRN_SCOPE -2
  44 
  45 static int mobility_rtas_call(int token, char *buf, s32 scope)
  46 {
  47         int rc;
  48 
  49         spin_lock(&rtas_data_buf_lock);
  50 
  51         memcpy(rtas_data_buf, buf, RTAS_DATA_BUF_SIZE);
  52         rc = rtas_call(token, 2, 1, NULL, rtas_data_buf, scope);
  53         memcpy(buf, rtas_data_buf, RTAS_DATA_BUF_SIZE);
  54 
  55         spin_unlock(&rtas_data_buf_lock);
  56         return rc;
  57 }
  58 
  59 static int delete_dt_node(__be32 phandle)
  60 {
  61         struct device_node *dn;
  62 
  63         dn = of_find_node_by_phandle(be32_to_cpu(phandle));
  64         if (!dn)
  65                 return -ENOENT;
  66 
  67         dlpar_detach_node(dn);
  68         of_node_put(dn);
  69         return 0;
  70 }
  71 
  72 static int update_dt_property(struct device_node *dn, struct property **prop,
  73                               const char *name, u32 vd, char *value)
  74 {
  75         struct property *new_prop = *prop;
  76         int more = 0;
  77 
  78         /* A negative 'vd' value indicates that only part of the new property
  79          * value is contained in the buffer and we need to call
  80          * ibm,update-properties again to get the rest of the value.
  81          *
  82          * A negative value is also the two's compliment of the actual value.
  83          */
  84         if (vd & 0x80000000) {
  85                 vd = ~vd + 1;
  86                 more = 1;
  87         }
  88 
  89         if (new_prop) {
  90                 /* partial property fixup */
  91                 char *new_data = kzalloc(new_prop->length + vd, GFP_KERNEL);
  92                 if (!new_data)
  93                         return -ENOMEM;
  94 
  95                 memcpy(new_data, new_prop->value, new_prop->length);
  96                 memcpy(new_data + new_prop->length, value, vd);
  97 
  98                 kfree(new_prop->value);
  99                 new_prop->value = new_data;
 100                 new_prop->length += vd;
 101         } else {
 102                 new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL);
 103                 if (!new_prop)
 104                         return -ENOMEM;
 105 
 106                 new_prop->name = kstrdup(name, GFP_KERNEL);
 107                 if (!new_prop->name) {
 108                         kfree(new_prop);
 109                         return -ENOMEM;
 110                 }
 111 
 112                 new_prop->length = vd;
 113                 new_prop->value = kzalloc(new_prop->length, GFP_KERNEL);
 114                 if (!new_prop->value) {
 115                         kfree(new_prop->name);
 116                         kfree(new_prop);
 117                         return -ENOMEM;
 118                 }
 119 
 120                 memcpy(new_prop->value, value, vd);
 121                 *prop = new_prop;
 122         }
 123 
 124         if (!more) {
 125                 of_update_property(dn, new_prop);
 126                 *prop = NULL;
 127         }
 128 
 129         return 0;
 130 }
 131 
 132 static int update_dt_node(__be32 phandle, s32 scope)
 133 {
 134         struct update_props_workarea *upwa;
 135         struct device_node *dn;
 136         struct property *prop = NULL;
 137         int i, rc, rtas_rc;
 138         char *prop_data;
 139         char *rtas_buf;
 140         int update_properties_token;
 141         u32 nprops;
 142         u32 vd;
 143 
 144         update_properties_token = rtas_token("ibm,update-properties");
 145         if (update_properties_token == RTAS_UNKNOWN_SERVICE)
 146                 return -EINVAL;
 147 
 148         rtas_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
 149         if (!rtas_buf)
 150                 return -ENOMEM;
 151 
 152         dn = of_find_node_by_phandle(be32_to_cpu(phandle));
 153         if (!dn) {
 154                 kfree(rtas_buf);
 155                 return -ENOENT;
 156         }
 157 
 158         upwa = (struct update_props_workarea *)&rtas_buf[0];
 159         upwa->phandle = phandle;
 160 
 161         do {
 162                 rtas_rc = mobility_rtas_call(update_properties_token, rtas_buf,
 163                                         scope);
 164                 if (rtas_rc < 0)
 165                         break;
 166 
 167                 prop_data = rtas_buf + sizeof(*upwa);
 168                 nprops = be32_to_cpu(upwa->nprops);
 169 
 170                 /* On the first call to ibm,update-properties for a node the
 171                  * the first property value descriptor contains an empty
 172                  * property name, the property value length encoded as u32,
 173                  * and the property value is the node path being updated.
 174                  */
 175                 if (*prop_data == 0) {
 176                         prop_data++;
 177                         vd = be32_to_cpu(*(__be32 *)prop_data);
 178                         prop_data += vd + sizeof(vd);
 179                         nprops--;
 180                 }
 181 
 182                 for (i = 0; i < nprops; i++) {
 183                         char *prop_name;
 184 
 185                         prop_name = prop_data;
 186                         prop_data += strlen(prop_name) + 1;
 187                         vd = be32_to_cpu(*(__be32 *)prop_data);
 188                         prop_data += sizeof(vd);
 189 
 190                         switch (vd) {
 191                         case 0x00000000:
 192                                 /* name only property, nothing to do */
 193                                 break;
 194 
 195                         case 0x80000000:
 196                                 of_remove_property(dn, of_find_property(dn,
 197                                                         prop_name, NULL));
 198                                 prop = NULL;
 199                                 break;
 200 
 201                         default:
 202                                 rc = update_dt_property(dn, &prop, prop_name,
 203                                                         vd, prop_data);
 204                                 if (rc) {
 205                                         printk(KERN_ERR "Could not update %s"
 206                                                " property\n", prop_name);
 207                                 }
 208 
 209                                 prop_data += vd;
 210                         }
 211 
 212                         cond_resched();
 213                 }
 214 
 215                 cond_resched();
 216         } while (rtas_rc == 1);
 217 
 218         of_node_put(dn);
 219         kfree(rtas_buf);
 220         return 0;
 221 }
 222 
 223 static int add_dt_node(__be32 parent_phandle, __be32 drc_index)
 224 {
 225         struct device_node *dn;
 226         struct device_node *parent_dn;
 227         int rc;
 228 
 229         parent_dn = of_find_node_by_phandle(be32_to_cpu(parent_phandle));
 230         if (!parent_dn)
 231                 return -ENOENT;
 232 
 233         dn = dlpar_configure_connector(drc_index, parent_dn);
 234         if (!dn) {
 235                 of_node_put(parent_dn);
 236                 return -ENOENT;
 237         }
 238 
 239         rc = dlpar_attach_node(dn, parent_dn);
 240         if (rc)
 241                 dlpar_free_cc_nodes(dn);
 242 
 243         of_node_put(parent_dn);
 244         return rc;
 245 }
 246 
 247 static void prrn_update_node(__be32 phandle)
 248 {
 249         struct pseries_hp_errorlog hp_elog;
 250         struct device_node *dn;
 251 
 252         /*
 253          * If a node is found from a the given phandle, the phandle does not
 254          * represent the drc index of an LMB and we can ignore.
 255          */
 256         dn = of_find_node_by_phandle(be32_to_cpu(phandle));
 257         if (dn) {
 258                 of_node_put(dn);
 259                 return;
 260         }
 261 
 262         hp_elog.resource = PSERIES_HP_ELOG_RESOURCE_MEM;
 263         hp_elog.action = PSERIES_HP_ELOG_ACTION_READD;
 264         hp_elog.id_type = PSERIES_HP_ELOG_ID_DRC_INDEX;
 265         hp_elog._drc_u.drc_index = phandle;
 266 
 267         handle_dlpar_errorlog(&hp_elog);
 268 }
 269 
 270 int pseries_devicetree_update(s32 scope)
 271 {
 272         char *rtas_buf;
 273         __be32 *data;
 274         int update_nodes_token;
 275         int rc;
 276 
 277         update_nodes_token = rtas_token("ibm,update-nodes");
 278         if (update_nodes_token == RTAS_UNKNOWN_SERVICE)
 279                 return -EINVAL;
 280 
 281         rtas_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
 282         if (!rtas_buf)
 283                 return -ENOMEM;
 284 
 285         do {
 286                 rc = mobility_rtas_call(update_nodes_token, rtas_buf, scope);
 287                 if (rc && rc != 1)
 288                         break;
 289 
 290                 data = (__be32 *)rtas_buf + 4;
 291                 while (be32_to_cpu(*data) & NODE_ACTION_MASK) {
 292                         int i;
 293                         u32 action = be32_to_cpu(*data) & NODE_ACTION_MASK;
 294                         u32 node_count = be32_to_cpu(*data) & NODE_COUNT_MASK;
 295 
 296                         data++;
 297 
 298                         for (i = 0; i < node_count; i++) {
 299                                 __be32 phandle = *data++;
 300                                 __be32 drc_index;
 301 
 302                                 switch (action) {
 303                                 case DELETE_DT_NODE:
 304                                         delete_dt_node(phandle);
 305                                         break;
 306                                 case UPDATE_DT_NODE:
 307                                         update_dt_node(phandle, scope);
 308 
 309                                         if (scope == PRRN_SCOPE)
 310                                                 prrn_update_node(phandle);
 311 
 312                                         break;
 313                                 case ADD_DT_NODE:
 314                                         drc_index = *data++;
 315                                         add_dt_node(phandle, drc_index);
 316                                         break;
 317                                 }
 318 
 319                                 cond_resched();
 320                         }
 321                 }
 322 
 323                 cond_resched();
 324         } while (rc == 1);
 325 
 326         kfree(rtas_buf);
 327         return rc;
 328 }
 329 
 330 void post_mobility_fixup(void)
 331 {
 332         int rc;
 333         int activate_fw_token;
 334 
 335         activate_fw_token = rtas_token("ibm,activate-firmware");
 336         if (activate_fw_token == RTAS_UNKNOWN_SERVICE) {
 337                 printk(KERN_ERR "Could not make post-mobility "
 338                        "activate-fw call.\n");
 339                 return;
 340         }
 341 
 342         do {
 343                 rc = rtas_call(activate_fw_token, 0, 1, NULL);
 344         } while (rtas_busy_delay(rc));
 345 
 346         if (rc)
 347                 printk(KERN_ERR "Post-mobility activate-fw failed: %d\n", rc);
 348 
 349         /*
 350          * We don't want CPUs to go online/offline while the device
 351          * tree is being updated.
 352          */
 353         cpus_read_lock();
 354 
 355         /*
 356          * It's common for the destination firmware to replace cache
 357          * nodes.  Release all of the cacheinfo hierarchy's references
 358          * before updating the device tree.
 359          */
 360         cacheinfo_teardown();
 361 
 362         rc = pseries_devicetree_update(MIGRATION_SCOPE);
 363         if (rc)
 364                 printk(KERN_ERR "Post-mobility device tree update "
 365                         "failed: %d\n", rc);
 366 
 367         cacheinfo_rebuild();
 368 
 369         cpus_read_unlock();
 370 
 371         /* Possibly switch to a new RFI flush type */
 372         pseries_setup_rfi_flush();
 373 
 374         return;
 375 }
 376 
 377 static ssize_t migration_store(struct class *class,
 378                                struct class_attribute *attr, const char *buf,
 379                                size_t count)
 380 {
 381         u64 streamid;
 382         int rc;
 383 
 384         rc = kstrtou64(buf, 0, &streamid);
 385         if (rc)
 386                 return rc;
 387 
 388         stop_topology_update();
 389 
 390         do {
 391                 rc = rtas_ibm_suspend_me(streamid);
 392                 if (rc == -EAGAIN)
 393                         ssleep(1);
 394         } while (rc == -EAGAIN);
 395 
 396         if (rc)
 397                 return rc;
 398 
 399         post_mobility_fixup();
 400 
 401         start_topology_update();
 402 
 403         return count;
 404 }
 405 
 406 /*
 407  * Used by drmgr to determine the kernel behavior of the migration interface.
 408  *
 409  * Version 1: Performs all PAPR requirements for migration including
 410  *      firmware activation and device tree update.
 411  */
 412 #define MIGRATION_API_VERSION   1
 413 
 414 static CLASS_ATTR_WO(migration);
 415 static CLASS_ATTR_STRING(api_version, 0444, __stringify(MIGRATION_API_VERSION));
 416 
 417 static int __init mobility_sysfs_init(void)
 418 {
 419         int rc;
 420 
 421         mobility_kobj = kobject_create_and_add("mobility", kernel_kobj);
 422         if (!mobility_kobj)
 423                 return -ENOMEM;
 424 
 425         rc = sysfs_create_file(mobility_kobj, &class_attr_migration.attr);
 426         if (rc)
 427                 pr_err("mobility: unable to create migration sysfs file (%d)\n", rc);
 428 
 429         rc = sysfs_create_file(mobility_kobj, &class_attr_api_version.attr.attr);
 430         if (rc)
 431                 pr_err("mobility: unable to create api_version sysfs file (%d)\n", rc);
 432 
 433         return 0;
 434 }
 435 machine_device_initcall(pseries, mobility_sysfs_init);

/* [<][>][^][v][top][bottom][index][help] */