static int dlpar_memory_add_by_index(u32 drc_index, struct property *prop) { struct of_drconf_cell *lmbs; u32 num_lmbs, *p; int i, lmb_found; int rc; pr_info("Attempting to hot-add LMB, drc index %x\n", drc_index); p = prop->value; num_lmbs = *p++; lmbs = (struct of_drconf_cell *)p; lmb_found = 0; for (i = 0; i < num_lmbs; i++) { if (lmbs[i].drc_index == drc_index) { lmb_found = 1; rc = dlpar_add_lmb(&lmbs[i]); break; } } if (!lmb_found) rc = -EINVAL; if (rc) pr_info("Failed to hot-add memory, drc index %x\n", drc_index); else pr_info("Memory at %llx (drc index %x) was hot-added\n", lmbs[i].base_addr, drc_index); return rc; }
static int dlpar_memory_readd_by_index(u32 drc_index, struct property *prop) { struct of_drconf_cell *lmbs; u32 num_lmbs, *p; int lmb_found; int i, rc; pr_info("Attempting to update LMB, drc index %x\n", drc_index); p = prop->value; num_lmbs = *p++; lmbs = (struct of_drconf_cell *)p; lmb_found = 0; for (i = 0; i < num_lmbs; i++) { if (lmbs[i].drc_index == drc_index) { lmb_found = 1; rc = dlpar_remove_lmb(&lmbs[i]); if (!rc) { rc = dlpar_add_lmb(&lmbs[i]); if (rc) dlpar_release_drc(lmbs[i].drc_index); } break; } } if (!lmb_found) rc = -EINVAL; if (rc) pr_info("Failed to update memory at %llx\n", lmbs[i].base_addr); else pr_info("Memory at %llx was updated\n", lmbs[i].base_addr); return rc; }
static int dlpar_memory_add_by_ic(u32 lmbs_to_add, u32 drc_index, struct property *prop) { struct of_drconf_cell *lmbs; u32 num_lmbs, *p; int i, rc, start_lmb_found; int lmbs_available = 0, start_index = 0, end_index; pr_info("Attempting to hot-add %u LMB(s) at index %x\n", lmbs_to_add, drc_index); if (lmbs_to_add == 0) return -EINVAL; p = prop->value; num_lmbs = *p++; lmbs = (struct of_drconf_cell *)p; start_lmb_found = 0; /* Navigate to drc_index */ while (start_index < num_lmbs) { if (lmbs[start_index].drc_index == drc_index) { start_lmb_found = 1; break; } start_index++; } if (!start_lmb_found) return -EINVAL; end_index = start_index + lmbs_to_add; /* Validate that the LMBs in this range are not reserved */ for (i = start_index; i < end_index; i++) { if (lmbs[i].flags & DRCONF_MEM_RESERVED) break; lmbs_available++; } if (lmbs_available < lmbs_to_add) return -EINVAL; for (i = start_index; i < end_index; i++) { if (lmbs[i].flags & DRCONF_MEM_ASSIGNED) continue; rc = dlpar_acquire_drc(lmbs[i].drc_index); if (rc) break; rc = dlpar_add_lmb(&lmbs[i]); if (rc) { dlpar_release_drc(lmbs[i].drc_index); break; } lmbs[i].reserved = 1; } if (rc) { pr_err("Memory indexed-count-add failed, removing any added LMBs\n"); for (i = start_index; i < end_index; i++) { if (!lmbs[i].reserved) continue; rc = dlpar_remove_lmb(&lmbs[i]); if (rc) pr_err("Failed to remove LMB, drc index %x\n", be32_to_cpu(lmbs[i].drc_index)); else dlpar_release_drc(lmbs[i].drc_index); } rc = -EINVAL; } else { for (i = start_index; i < end_index; i++) { if (!lmbs[i].reserved) continue; pr_info("Memory at %llx (drc index %x) was hot-added\n", lmbs[i].base_addr, lmbs[i].drc_index); lmbs[i].reserved = 0; } } return rc; }
static int dlpar_memory_add_by_count(u32 lmbs_to_add, struct property *prop) { struct of_drconf_cell *lmbs; u32 num_lmbs, *p; int lmbs_available = 0; int lmbs_added = 0; int i, rc; pr_info("Attempting to hot-add %d LMB(s)\n", lmbs_to_add); if (lmbs_to_add == 0) return -EINVAL; p = prop->value; num_lmbs = *p++; lmbs = (struct of_drconf_cell *)p; /* Validate that there are enough LMBs to satisfy the request */ for (i = 0; i < num_lmbs; i++) { if (!(lmbs[i].flags & DRCONF_MEM_ASSIGNED)) lmbs_available++; } if (lmbs_available < lmbs_to_add) return -EINVAL; for (i = 0; i < num_lmbs && lmbs_to_add != lmbs_added; i++) { rc = dlpar_acquire_drc(lmbs[i].drc_index); if (rc) continue; rc = dlpar_add_lmb(&lmbs[i]); if (rc) { dlpar_release_drc(lmbs[i].drc_index); continue; } lmbs_added++; /* Mark this lmb so we can remove it later if all of the * requested LMBs cannot be added. */ lmbs[i].reserved = 1; } if (lmbs_added != lmbs_to_add) { pr_err("Memory hot-add failed, removing any added LMBs\n"); for (i = 0; i < num_lmbs; i++) { if (!lmbs[i].reserved) continue; rc = dlpar_remove_lmb(&lmbs[i]); if (rc) pr_err("Failed to remove LMB, drc index %x\n", be32_to_cpu(lmbs[i].drc_index)); else dlpar_release_drc(lmbs[i].drc_index); } rc = -EINVAL; } else { for (i = 0; i < num_lmbs; i++) { if (!lmbs[i].reserved) continue; pr_info("Memory at %llx (drc index %x) was hot-added\n", lmbs[i].base_addr, lmbs[i].drc_index); lmbs[i].reserved = 0; } } return rc; }
static int dlpar_memory_remove_by_count(u32 lmbs_to_remove, struct property *prop) { struct of_drconf_cell *lmbs; int lmbs_removed = 0; int lmbs_available = 0; u32 num_lmbs, *p; int i, rc; pr_info("Attempting to hot-remove %d LMB(s)\n", lmbs_to_remove); if (lmbs_to_remove == 0) return -EINVAL; p = prop->value; num_lmbs = *p++; lmbs = (struct of_drconf_cell *)p; /* Validate that there are enough LMBs to satisfy the request */ for (i = 0; i < num_lmbs; i++) { if (lmb_is_removable(&lmbs[i])) lmbs_available++; } if (lmbs_available < lmbs_to_remove) { pr_info("Not enough LMBs available (%d of %d) to satisfy request\n", lmbs_available, lmbs_to_remove); return -EINVAL; } for (i = 0; i < num_lmbs && lmbs_removed < lmbs_to_remove; i++) { rc = dlpar_remove_lmb(&lmbs[i]); if (rc) continue; lmbs_removed++; /* Mark this lmb so we can add it later if all of the * requested LMBs cannot be removed. */ lmbs[i].reserved = 1; } if (lmbs_removed != lmbs_to_remove) { pr_err("Memory hot-remove failed, adding LMB's back\n"); for (i = 0; i < num_lmbs; i++) { if (!lmbs[i].reserved) continue; rc = dlpar_add_lmb(&lmbs[i]); if (rc) pr_err("Failed to add LMB back, drc index %x\n", lmbs[i].drc_index); lmbs[i].reserved = 0; } rc = -EINVAL; } else { for (i = 0; i < num_lmbs; i++) { if (!lmbs[i].reserved) continue; dlpar_release_drc(lmbs[i].drc_index); pr_info("Memory at %llx was hot-removed\n", lmbs[i].base_addr); lmbs[i].reserved = 0; } rc = 0; } return rc; }